DP总览
问题特点
计数(多少种)
- Li114,多少种路径
- 多少种方法选出k个数,使得和是sum
最大值
- Li669,硬币的最少个数
- Li397,最长上升子序列
存在性(可行性、能否)
- Li116,能否跳到最后一块石头
解题步骤
-
确定状态
- 考虑最后一步(最后一个物品,最后一个路径)
- 变成解决子问题了(规模更小的问题)
- 状态就是 f 对应的 dp
-
确定状态转移方程
- ❗ dp[i] 和 f(i) 不完全一样
P2O_2e 14
,Li515
- dp[i]的计算顺序(从大到小还是从小到达)有影响
0-1背包
- ❗ dp[i] 和 f(i) 不完全一样
-
分析初始条件和边界情况
- 初始条件:开始的几项,和后面规则不一样的值
- 边界情况:数组下标越界时,无法实现的情况的dp值(-1,无穷还是什么)
-
确定计算dp的顺序
- 原则就是计算需要的都是之前计算的结果
- 一般都是从小到大,背包问题的空间优化必须反向计算
空间优化
- 使用滚动数组, 根据状态转移方程中需要的最旧的数据确定大小
- 用
dp[i % n]
代替dp[i]是最方便, 最好理解的解决办法, 其中n是压缩后的数组大小 - 一般是逐行扫描, 滚动数组长度是列数的倍数。 如果列多行少时, 可以考虑逐列扫描让滚动数组长度是列数的倍数, 进一步优化空间
坐标型20%
简单例题
Li114 不同路径
Li115 不同路径,网格中有障碍
问题特点
-
给定一个序列或者网格
-
状态dp[i]的含义是以a[i]结尾的子序列的性质
Li397 最长连续单向子序列
Li110 路径数字和的最小值
Li553 炸弹袭击
序列型20%
简单例题
Li515 刷房子
问题特点
- 状态dp[i]的含义是前i个元素的性质
- 初始化时,dp[0]表示空序列的性质
- ❗ for循环里
i <= n
, 经常写成i < n
,导致输出0
Li556 刷房子, O(n*k)
Li644 数位中1的个数
L198_Li392 打家劫舍
划分型20%
简单例题
Li512 编码解析方法
区间型15%
背包型10%
载重W的背包,N件待选物品,物品属性:重量w,价值v
0-1背包
列表中的物品只有一个
- 最大价值
- 要求正好装满
- 不要求正好装满
- 能否装满
完全背包
列表种的物品有任意个