完全背包问题是每件物品有无限个
完全背包问题的状态表示和01背包问题一样
dp[i][j]表示只看前i个物品,总体积<= j的最大价值
状态计算:
按照第i个物品选了多少个来分
然后综合起来就是
k是枚举的第i个物品的个数,k = 0, 1, 2,...
三层循环的二维做法
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1010; 4 int dp[N][N]; 5 int v[N], w[N]; 6 int main() { 7 int n, m; 8 cin >> n >> m; 9 for (int i = 1; i <= n; i++) { 10 cin >> v[i] >> w[i]; 11 } 12 for (int i = 1; i <= n; i++) { 13 for (int j = 0; j <= m; j++) { 14 for (int k = 0; k * v[i] <= j; k++) { //枚举一下物品个数,k个物品一定要小于等于j 15 dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i] * k] + w[i] * k); 16 } 17 } 18 } 19 cout << dp[n][m] << endl; 20 return 0; 21 }
完全背包问题可以优化乘两层循环
这是两层循环,二维的解法
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1010; 4 int dp[N][N]; 5 int v[N], w[N]; 6 int main() { 7 int n, m; 8 cin >> n >> m; 9 for (int i = 1; i <= n; i++) { 10 cin >> v[i] >> w[i]; 11 } 12 for (int i = 1; i <= n; i++) { 13 for (int j = 0; j <= m; j++) { 14 dp[i][j] = dp[i - 1][j]; 15 if (j >= v[i]) { 16 dp[i][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]); 17 } 18 } 19 } 20 cout << dp[n][m] << endl; 21 return 0; 22 }
完全背包问题也可以优化到一维
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1010; 4 int dp[N]; 5 int v[N], w[N]; 6 int main() { 7 int n, m; 8 cin >> n >> m; 9 for (int i = 1; i <= n; i++) { 10 cin >> v[i] >> w[i]; 11 } 12 for (int i = 1; i <= n; i++) { 13 for (int j = v[i]; j <= m; j++) { 14 dp[j] = max(dp[j], dp[j - v[i]] + w[i]); 15 } 16 } 17 cout << dp[m] << endl; 18 return 0; 19 }