第五周 动态规划
一、概括
- “Simplifying a complicated problem by breaking it down into simpler sub-problems” (in a recursive manner)
- Divide & Conquer + Optimal substructure 分治+最优子结构
1、DP、递归、分治区别(importance)
- 看是否有最优子结构,有则DP
- 共性:找到重复子问题
- 差异性:有最优子结构、中途可以淘汰次优解
- 分治:每一步都没有最优解,所以会出现复杂度指数级
2、记忆化搜索(自顶向下)
- 增加缓存
- 熟练后建议用自低向上递推(for)
回忆分治:如下— 起点分解成 从B走和从A,然后两个结果相加
(只能向右和向下,如果可以斜边,就会出现重复问题,例如B会走向C。这个就是高级DP)
自低向上
计算:当前数等于右边+下面的值(状态存储)。自底向上,(这是简单的dp,复杂的dp需要考虑重复计算问题)
最后地推出如下:
3、状态转移方程(DP方程)
- 继续上一题的 问题(把障碍物想象成0)
opt[i,j] = opt[i + 1][j] + opt[i][j + 1];
//完整逻辑
if a[i][j] == "空地" :
opt[i][j] = opt[i + 1][j] + opt[i][j + 1];
else
opt[i][j] = 0;
4、动态规划关键点
- 最优子结构
opt[n] = best_of(opt[n - 1], opt[n - 2],...);
- 存储中间状态:
opt[i]
- 递推公式(美其名曰:状态转移方程或者DP方程)
- Fib:
opt[n] = opt[n - 1] + opt[n - 2]
- 二维路径:
opt[i][j] = opt[i + 1][j] + opt[i][j + 1]
(且判断a[i][j]是否空地)
- Fib:
5、DP模板(三角形最小路径和案例模板)
- 重复性(分治)
problem(i,j) = min(sub(i+1, j),sub(i+1, j+1)) + a[i,j]
- 定义状态数组
f[i,j]
- DP方程:
f[i,j] = min(f(i+1, j),f(i+1, j+1)) + a[i,j]