动态规划
+ 感觉要写好久.. 但确实考的很多动态规划问题
1. 数字三角形模型
状态表示:f[i, j] 所有从起点走到(i, j)的路径中数字和最大值
f[i, j] = max(f[i - 1, j - 1] + a[i, j], f[i - 1, j - 1])
2. 序列问题
2.1 最长上升子序列问题
状态表示:f[i], 以i结尾的序列长度
记录方案:额外开一个数组 保存转移的过程
o(nlogn)版本:
最小值一定是单调递增的,所以对于最长子序列而言,只用在每种长度有一个结尾更小的;
因此找到最大的 小于a_i的书 直接更新最小值 a_i+1
2.2 最长公共子序列
状态表示:f[i, j]表示第一个字符串从0-i, 第二个字符串从0-j,无需以当前元素结尾;
f[i, j ] = max(f[i - 1][j], f[i][j - 1], f[i - 1][j - 1] + 1);
2.3 编辑距离
2.4 正则表达式匹配
2.5 高楼扔鸡蛋
状态表示:f[i, j] 用j个鸡蛋,尝试i次可以得到的最高高度
f[i, j] = f[i - 1, j] + 1 + f[i - 1, j - 1]
3. 背包问题合集
3.1 0-1背包问题
状态表示:f[i, j]表示只能从前i个物品里选,总体积 <= j的方案
优化:只用到j - vi 一维数组 从右向左更新
3.2 完全背包问题
除了遍历顺序是从左到右,剩下和0-1背包问题完全一致
3.3 多重背包问题
优化方式:二进制打包优化;
3.4 分组背包问题
问题:分组,每组只能选一个 因此多了一个遍历组的过程 -> 组内0/1背包
3.5 背包问题求具体方案
f[i, j] = max(f[i - 1, j], f[i - 1, j - v[i]] + w[i]);
最后输出f[n, m]
其实是判断每个物品是否备选,倒退出来再这个状态转移方程中,选择是的第一项还是第二项
具体区别:
不能用状态压缩的方式 -> 两维状态循环无所谓
判断f[n][m]倒退,判断是否从上一状态转移过来
0-1背包问题求方案: (字典序最小-> 贪心的选(可选可不选,因为字典序最小,就要选)
3.6 背包问题求方案数
最优解的方案数 -> 有点像路径条数
f[i, j]
新开一个g[i, j] f[i, j] 取最大值的方案数
分三种情况:
f[i - 1, j] 大 g[i - 1][j]
f[i - 1, j - v[i]] + w[i] 大, g[i - 1, j - v[i]]
相等:两个想加
-> 可以用一维来写
4. 状态机模型
5. 状态压缩DP
6. 区间DP
7. 树形DP
8. 数位DP
9. 单调队列优化的DP问题
Last updated