c++背包模板
一.01背包
方法1:二维数组
(题目【模板】:洛谷P1048)
#include <bits/stdc++.h> using namespace std; const int N = 1e3 + 10; int n, V; int w[N], v[N]; int dp[N][N]; signed main() { scanf("%d%d", &V, &n); for (int i = 1;i <= n;i++) { scanf("%d%d", &w[i], &v[i]); } for (int i = 1;i <= n;i++) { for (int j = 1;j <= V;j++) { if (j < w[i]) dp[i][j] = dp[i-1][j]; else dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]); } } printf("%d", dp[n][V]); return 0; }
方法二:一维数组滚动优化
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n, V; int w[N], v[N]; int dp[N]; signed main() { scanf("%d%d", &V, &n); for (int i = 1;i <= n;i++) { scanf("%d%d", &w[i], &v[i]); } for (int i = 1;i <= n;i++) { for (int j = V;j >= w[i];j--) { dp[j] = max(dp[j], dp[j-w[i]]+v[i]); } } printf("%d", dp[V]); return 0; }
二.完全背包
其实就是把01背包的只有1件物品,改成了有无限件物品可以选择;
代码:
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n, V; int w[N], v[N]; int dp[N]; signed main() { scanf("%d%d", &V, &n); for (int i = 1;i <= n;i++) { scanf("%d%d", &w[i], &v[i]); } for (int i = 1;i <= n;i++) { for (int j = 0;j <= V;j++) //注意这里是正着循环 { if (j >= w[i]) dp[j] = max(dp[j], dp[j-w[i]]+v[i]); } } printf("%d", dp[V]); return 0; }
三.多重背包
限制每个物品有s[i]个,求最大价值
代码(未优化):
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int n, V; int w[N], v[N]; int dp[N], cnt = 1; signed main() { scanf("%d%d", &V, &n); for (int i = 1;i <= n;i++) { int vi, wi, si; //价值,重量,数量 scanf("%d%d%d", &wi, &vi, &si); for (int j = 1;j <= si;j++) { v[cnt] = vi; w[cnt] = wi; cnt++; //将多重背包拆成01背包 } } for (int i = 1;i <= cnt;i++) { for (int j = V;j >= w[i];j--) { dp[j] = max(dp[j], dp[j-w[i]]+v[i]); } } printf("%d", dp[V]); return 0; }
优化:
int cnt = 1; for (int i = 1;i <= n;i++) { int vi, wi, si; //价值,重量,数量 scanf("%d%d%d", &wi, &vi, &si); int k = 1; while (k <= si) { v[cnt] = vi * k; w[cnt] = wi * k; si -= k; k *= 2; cnt++; } if (si > 0) { cnt++; v[cnt] = vi * si; w[cnt] = wi * si; } }
完结撒花(其实啥也没讲)
luogu:XiaoyuWan_

浙公网安备 33010602011771号