Dynamic Programming¶
约 490 个字 55 行代码 8 张图片 预计阅读时间 4 分钟
- DP 常用于解决 最优化问题 和计数问题。
- 一般而言,用 DP 解决的问题需要具有以下特征:
- 最优子结构
- 无后效性
- 用空间换时间,我们常常需要一个状态值表示对于当前状态的答案(可能是截至当前状态)
Fibonacci Numbers¶
\[F(N) = F(N-1) + F(N-2)\]
C | |
---|---|
1 2 3 4 5 6 |
|
\[ T(N) \geq T(N-1) + T(N-2) \]
- 问题:我们多次计算了相同的子问题,产生了很多额外的开销。
- 解决:从底向上,答案等于当前结果和前一个答案之和。
C | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
Ordering Matrix Multiplications¶
矩阵具有结合律,通过不同的组合会有不同的时间开销。
令\(b_n\) = number of different ways to compute \(M_1\), \(M_2\), \(···\), \(M_n\) 我们有\(b_2 = 1, b_3 = 2, b_4 = 5, \cdots\).令\(M_i\)是\(r_{i-1} \times r_i\)矩阵,\(M_{ij} = M_i \cdots M_j\).那么\(M_{1n} = M_1 \cdots M_n = M_{1i} \cdot M_{i+1 n}\)
所以\(b_n = \sum_{i=1}^{n-1} b_i b_{n-i}\)
\[b_n = O(\frac{4^n}{n\sqrt{n}})\]

C | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
\[ T(N) = O(N^3) \]
Optimal Binary Search Tree¶
选根就行。下面是选根(每一个子问题)的具体操作。
最终三种树的cost:
All Pairs Shortest Path¶
- Method 1 (Dijkstra算法)
循环调用dijkstra算法。\(T(N) = O(|V|^3)\)
- Method 2 (Floyd算法)
定义 \(D^k[i][j]\) = min{length of path i -> {l <= k} -> j} 和 \(D^{-1}[i][j]\) = \(Cost[i][j]\)。
上标 k 是指从 i 到 j 的路径可以经过编号为 0 到 k 的节点。
我们定义子问题,能得到如下式子:
\[
D^k[i][j] = \min \{ D^{k-1}[i][j], D^{k-1}[i][k] + D^{k-1}[k][j] \}, \quad k \geq 0
\]
初始状态是\(D^{-1}[i][j]\),最终状态是\(D^{N-1}[i][j]\)。
C | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Floyd算法的时间复杂度为:
\[
T(N) = O(N^3)
\]
但是在稠密图中速度更快。
Product Assembly¶
- Two assembly lines for the same car
- Different technology (time) for each stage
- One can change lines between stages
- Minimize the total assembly time
- Exhaustive search gives \(O( 2^N )\) time + \(O( N )\) space
为什么决定用动态规划?