定义
- 将原问题拆成多个子问题,保留子问题的解
- 关键是找到状态转移方程
典型题
1. 依赖相邻(一维爬梯子,二维找路线);依赖不相邻(分割)
542. 01 Matrix
找每个位置最近的0的距离:左上到右下走一遍, 右下到左上走一遍
221. Maximal Square
由1构成的最大正方形:(i, j)
记录以此为右下角的最大正方形边长;当(i, j)
位置为1时,dp[i][j] = min(dp[i][j-1], dp[i-1][j-1], dp[i-1][j]) + 1
压缩空间:二维变一维,一维变变量
1143. Longest Common Subsequence
最长公共子序列:二维dp,字符相等dp[i][j] = dp[i-1][j-1] + 1
,不相等dp[i][j] = max(dp[i][j-1], dp[i-1][j])
279. Perfect Squares
求正整数最少拆成几个平方数:dp[i] = min(dp[i], dp[i-j*j]) + 1
139. Word Break
输出是否可分割成可以在集合里找到的子串:dp
bool vector记录此位置是否可以达到标准,如果substring在字符串里存在,则dp[i] = dp[i-len]
650. 2 Keys Keyboard
复制粘贴字符达到一定长度的最小次数:dp[j] + dp[i/j]
2. 背包问题(与sum有关)
- N个物品,W容量,每个物品体积w价值v
- 0-1背包:只能选或不选;完全背包:不限定数量
- 思路:
dp[i][j]
表示前i
件物品总价值不超过j
的
// dp[N][W]即答案
// 通常N放外层
// 压缩空间至一维思路很简单,在此省略
for (int i = 1; i <= N; i++) {
// N个物品,即weights和values长度均为N
int w = weights[i-1], v = values[i-