专栏文章
一般 DP 转移方程
算法·理论参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioiojm8
- 此快照首次捕获于
- 2025/12/02 19:50 3 个月前
- 此快照最后确认于
- 2025/12/02 19:50 3 个月前
动态规划(DynamIc ProgrammIng,或称 DP)算法通常用于全局求解某种具有最优性质的问题。
动态规划算法与分治法类似,其基本思想也是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中得到原有问题的解。与分治法不同的是,动态规划经分解后得到的子问题往往不是相互独立 的。
动态规划算法与分治法类似,其基本思想也是将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解中得到原有问题的解。与分治法不同的是,动态规划经分解后得到的子问题往往不是相互独立 的。
1. 常见的线性 DP(LInear DP)
这应该是最简单的 DP 模型了。这个模型用于解决所有呈线性的状态转移的 DP。
符号说明
= 序列总长度;
= 动态规划状态数组;
= 所求子序列长度;
= 原始序列(索引从 开始);
= 其他序列(同理,在 LCS 等会用到);
= 动态规划状态数组;
= 所求子序列长度;
= 原始序列(索引从 开始);
= 其他序列(同理,在 LCS 等会用到);
1.1 LIS 最长上升子序列
一般性的问题:求序列中严格递增的最长子序列长度(元素不要求连续)。
状态定义: 表示以第 个元素结尾的最长上升子序列长度。
转移方程:
初始值:
结果:
状态定义: 表示以第 个元素结尾的最长上升子序列长度。
转移方程:
初始值:
结果:
1.2 LNDS 最长不降子序列
一般性的问题:求序列中非递减的最长子序列(允许相等元素)。
状态定义: 表示以第 个元素结尾的最长不降子序列长度。
转移方程:
初始值:
结果:
状态定义: 表示以第 个元素结尾的最长不降子序列长度。
转移方程:
初始值:
结果:
1.3 LNIS 最长不升子序列
一般性的问题:求序列中非递增的最长子序列(允许相等元素)。
状态定义: 表示以第 个元素结尾的最长不升子序列长度。
转移方程:
初始值:
结果:
状态定义: 表示以第 个元素结尾的最长不升子序列长度。
转移方程:
初始值:
结果:
1.4 LCS 最长公共子序列
一般性的问题:求两个序列的最长公共子序列(元素不要求连续)。
状态定义: 表示序列 A 前 个元素与序列 B 前 个元素的最长公共子序列长度。
转移方程:
初始值:
结果:
状态定义: 表示序列 A 前 个元素与序列 B 前 个元素的最长公共子序列长度。
转移方程:
初始值:
结果:
2. 常见的背包 DP(Knapsack DP)
也是最常见的 DP 模型,用于解决贪心不能解决的在有限容量下选择物品以获得最优的问题。(下列叙述将仅叙述其特征!)
符号说明
= 背包容量;
= 动态规划状态数组;
= 第 件物品的价值;
= 第 件物品的重量(代价);
= 第 件物品的数量;
= 动态规划状态数组;
= 第 件物品的价值;
= 第 件物品的重量(代价);
= 第 件物品的数量;
2.1 01 背包
特征要素:
- 每件物品只有 样
那么考虑:设 表示选择(单样或不选)前 个物品在占用不超过 容量时的最大的价值。
思路:考虑打擂台(选最优嘛)。
思路:考虑打擂台(选最优嘛)。
- 选第 件物品,则此时的 ;
- 不选,就是 。 此时,状态转移方程就是:
实现时需要注意:逆推 + 滚动数组会更优!
2.2 ON 背包(完全背包)
题外话
0N 背包是因为机房里有很多人喜欢写这样子的代码:
CPPconst Int N=0x7f7f7f7f;
而这个数很大,可以说是无穷大(对于
Int 来说)。而完全背包又刚刚好对应的下面的要素。特征要素:
- 每件物品有无数样
那么考虑:设 表示选择(多样或不选)前 个物品在占用不超过 容量时的最大的价值。
思路:由于有无限个物品,所以需要考虑第 个物品选择 个最合适。同样, 的设定同上。
思路:由于有无限个物品,所以需要考虑第 个物品选择 个最合适。同样, 的设定同上。
- 选 件第 件物品,则此时的 ,当然,不能超过背包容量 ;
- 不选,就是 。 此时,状态转移方程就是:
- 当然,由于三重循环可能会爆 TLE,所以在实现时可以考虑每次比上次多选一件或不选,再取最大值。
实现时需要注意:顺推 + 滚动数组会更优!
2.3 0C 背包(多重背包中的有限数量背包)
还是题外话
0C 背包是因为定义的 表示的是其数量。
特征要素:
- 每件物品有 样
那么考虑:设 表示选择(不超过 样或不选)前 个物品在占用不超过 容量时的最大的价值。
思路一(从完全背包推演):由于只有 个物品,所以需要考虑第 个物品选择 (下文的 同理)个最合适。同样, 的设定同上。
思路一(从完全背包推演):由于只有 个物品,所以需要考虑第 个物品选择 (下文的 同理)个最合适。同样, 的设定同上。
- 选 件第 件物品,则此时的 ,当然,不能超过背包容量 ;
- 不选,就是 。 此时,状态转移方程就是:
- 当然,由于三重循环可能会爆 TLE,所以在实现时可以考虑每次比上次多选一件或不选,再取最大值。
思路二(从 01 背包推演):将每个有限件的物品拆开成单个独立的物品。然后套 01 背包。
- 需要优化:因为这样相当于二进制选择,而其会出现很多种重复的方案。所以考虑倍增(二次幂)优化:将一个物品拆成这样的序列:,然后将价值和重量套回去就可以了!
- 请注意:对于高次幂的物品倍增方法(如果 ,那就会适得其反),因为每增加一个进制单位,就会冗余一个单件的物品(除非你刚刚好是某个进制的前几项的和),反而会效果变差。
实现时:用 01 背包就可以了。(单调 Que 还不会,我太蒟了)
3. 常见的区间 DP(Interval DP)
这算一个线性 DP 的扩展版。
符号说明
= 动态规划状态数组;
= 序列的第 个元素;
= 序列的第 在合并后的价值;
= 序列的第 个元素;
= 序列的第 在合并后的价值;
一般性的问题:在一个序列中合并相邻的两个元素使得其价值最优。
状态定义: 表示序列在合并 和 两堆时最优。
思路:因为是要合并两堆,所以会是合并于子序列 和 的最优值。既然是要取最优值,就要遍历所有可能的 。注意到若 时,价值是固定的(提前处理价值 )。
转移方程: 初始值:
结果:
状态定义: 表示序列在合并 和 两堆时最优。
思路:因为是要合并两堆,所以会是合并于子序列 和 的最优值。既然是要取最优值,就要遍历所有可能的 。注意到若 时,价值是固定的(提前处理价值 )。
转移方程: 初始值:
结果:
4. 常见的树形 DP(Tree DP)
5. 常见的状压 DP(State Compression DP)
6. 记忆化 DFS(MemoizatIon DFS)
7. 记忆化 BFS(MemoizatIon BFS)
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...