📘 DP入门总结
✍️ 作者:桑榆
🕓 更新时间:2026-04-02
🧠 关键词:dp、动态规划
DP入门总结
前面刷过几道题,可以分成以下几类
1.线性递推型
特点是:dp[i]通常只依赖前面一两个状态。
典型题:
- 斐波那契数
- 爬楼梯
- 使用最小花费爬楼梯
常见形式:
javascript
dp[i] = dp[i - 1] + dp[i - 2]
dp[i] = Math.min(dp[i - 1], dp[i - 2]) + ...关注点:
dp[i]表示什么- 当前状态从前几个状态转移过来
- 初始值是什么
2.选择型 DP
特点是: 当前位置通常有"选"或者"不选"两种决策。
典型题:
- 打家劫舍
- 打家劫舍Ⅱ
核心思路:
javascript
dp[i] = Math.max(不选当前, 选当前)比如打家劫舍:
javascript
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i])3.二维路径型DP
特点是:状态在一个网格里,通常从"上面"或"左边"转移过来。
典型题:
- 不同路径
- 不同路径Ⅱ
常见形式:
javascript
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]如果有障碍物,就多一层判断:
javascript
if (障碍物) dp[i][j] = 0关注点:
dp[i][j]表示到哪个格子的结果- 当前位置能从哪几个方向过来
- 第一行、第一列怎么初始化
4.枚举分割点型DP
特点是:要求dp[i]时,不是只看前一两个状态,而是要枚举所有切分方式。
典型题:
整数拆分不同的二叉搜索树
常见写法:
javascript
for (let i = ...; i <= n; i++) {
for (let j = 1; j < i; j++) {
// 枚举分割点
}
}这类题的关键是: 我把当前问题拆成左右两部分,怎么利用子问题结果?
区别在于:
- 整数拆分:取最大值
- 不同 BST:统计总方案数
5.求最值vs求方案数
这是一个非常重要的横向分类。
求最值的题:
使用最小花费爬楼梯打家劫舍整数拆分
特征:
javascript
Math.max(...)
Math.min(...)求方案数的题:
- 爬楼梯
- 不同路径
- 不同的二叉搜索树
特征:
javascript
dp[...] += ...
dp[...] = ... + ...