分组背包问题是物品有n组,每组里面有若干个物品,每组里最多选一个。
dp[i][j]只从前i组物品中选,且总体积不大于j的最大价值
状态计算:枚举第i组物品选哪个或不选
不选第i组物品,选第i组的第1个物品,选第i组的第2个物品,等等等等
二维做法
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 110; //一共有100组物品 4 int s[N]; //每组物品所含的物品数 5 int v[N][N], w[N][N]; 6 int dp[N][N]; 7 int main() { 8 int n, m; 9 cin >> n >> m; 10 for (int i = 1; i <= n; i++) { 11 cin >> s[i]; 12 for (int j = 1; j <= s[i]; j++) { 13 cin >> v[i][j] >> w[i][j]; 14 } 15 } 16 for (int i = 1; i <= n; i++) { 17 for (int j = 0; j <= m; j++) { 18 dp[i][j] = dp[i - 1][j]; //不选 19 for (int k = 1; k <= s[i]; k++) { 20 if (j >= v[i][k]) { 21 dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i][k]] + w[i][k]); 22 } 23 } 24 } 25 } 26 cout << dp[n][m] << endl; 27 return 0; 28 }
一维做法
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 110; 4 int s[N], v[N][N], w[N][N], dp[N]; 5 int main() { 6 int n, m; 7 cin >> n >> m; 8 for (int i = 1; i <= n; i++) { 9 cin >> s[i]; 10 for (int j = 1; j <= s[i]; j++) { 11 cin >> v[i][j] >> w[i][j]; 12 } 13 } 14 for (int i = 1; i <= n; i++) { 15 for (int j = m; j >= 0; j--) { 16 for (int k = 1; k <= s[i]; k++) { 17 if (j >= v[i][k]) { 18 dp[j] = max(dp[j], dp[j - v[i][k]] + w[i][k]); 19 } 20 } 21 } 22 } 23 cout << dp[m] << endl; 24 return 0; 25 }