与01背包的区别:
01背包中每件物品只能拿一次,而完全背包中的物品可以拿无限次。
代码上的区别
前者的二层循环是逆序,而后者则是顺序
01
顺序
朴素解法,暴力三重循环:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include<iostream>
using namespace std;
const int N = 1010; int dp[N][N]; int w[N]; int v[N];
int main() { int n, weight; scanf("%d%d", &n, &weight);
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 <= weight; j++) for (int k = 1; k * w[j] <= j; k++) dp[i][j] = max(dp[i][j], dp[i - 1][j - k * w[j]] + k * v[j]); printf("%d\n", dp[n][weight]); }
|
优化解法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include<iostream>
using namespace std;
const int N = 10000; int v[N]; int w[N]; int f[N][N];
int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d%d", &v[i], &w[i]); f[0][0] = 0; for (int i = 1; i <= n; i++) for (int j = 0; j <= m; j++) { f[i][j] = f[i - 1][j]; if (j >= v[i]) f[i][j] = max(f[i][j], f[i][j - v[i]] + w[i]); } printf("%d\n", f[n][m]); return 0; }
|