// 01 背包 for (int i = 1; i <= n; i++) for (int j = m; j >= v[i]; j--) f[j] = max(f[j], f[j - v[i]] + w[i]);
// 完全背包 for (int i = 1; i <= n; i++) for (int j = v[i]; j <= m; j++) f[j] = max(f[j], f[j - v[i]] + w[i]);
多重背包 / 分组背包
1 2 3 4 5 6 7
// 分组背包 for (int i = 1; i <= n; i++) for (int j = m; j >= 0; j--) for (int k = 0; k < (int)group[i].size(); k++) { int v = group[i][k].first, w = group[i][k].second; if (j >= v) f[j] = max(f[j], f[j - v] + w); }
LIS / LCS / 编辑距离
1 2 3 4 5 6
// O(n^2) LIS for (int i = 1; i <= n; i++) { f[i] = 1; for (int j = 1; j < i; j++) if (a[j] < a[i]) f[i] = max(f[i], f[j] + 1); }
区间 DP
1 2 3 4 5 6 7
for (int len = 2; len <= n; len++) for (int l = 1; l + len - 1 <= n; l++) { int r = l + len - 1; f[l][r] = 1e9; for (int k = l; k < r; k++) f[l][r] = min(f[l][r], f[l][k] + f[k + 1][r] + s[r] - s[l - 1]); }
状压 DP / 树形 DP / 记忆化搜索
1 2 3 4 5 6 7 8 9 10
// 树形 DP 例:没有上司的舞会 voiddfs(int u){ f[u][1] = happy[u]; for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; dfs(j); f[u][0] += max(f[j][0], f[j][1]); f[u][1] += f[j][0]; } }