注意点:
最后在输出的时候输出的是dp[小组数][背包容量],而不是dp[物品数量][背包容量]。
还有就是01背包是取或不取这个物品,放在物品循环或者背包容量循环里(取决于遍历顺序);分组背包是取与不取这组物品,放在遍历小组物品之前。
01背包核心代码:
for (int i = 1; i <= n; i++) {
for (int j = 0; j < m; j++) {
dp[i][j] = dp[i - 1][j];
if (wei[i] <= j) {
dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - wei[i]] + val[i]);
}
}
}
分组背包核心代码:
for (int i = 1; i <= maxt; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j] = dp[i - 1][j];
for (int k = 0; k < siz[i]; k++) {
if (wei[i][k] <= j) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - wei[i][k]] + uval[i][k]);
}
}
}
}
代码:
#include<iostream>
#include<algorithm>
#define MAX 3000
using namespace std;
int siz[MAX];//下标代表组号,值代表组里有几个物品
int uval[MAX][MAX];//uval[i][j]表示第i组的第j个物品的利用价值
int wei[MAX][MAX];//wei[i][j]表示第i组的第j个物品的重量
int dp[MAX][MAX];
int main() {
int m, n;
cin >> m >> n;
int w, v, s;
int maxt = 0;
for (int i = 1; i <= n; i++) {
scanf("%d%d%d", &w, &v, &s);
uval[s][siz[s]] = v;
wei[s][siz[s]] = w;
siz[s]++;
maxt = max(maxt, s);
}
for (int i = 1; i <= maxt; i++) {
for (int j = 0; j <= m; j++) {
dp[i][j] = dp[i - 1][j];
for (int k = 0; k < siz[i]; k++) {
if (wei[i][k] <= j) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - wei[i][k]] + uval[i][k]);
}
}
}
}
cout << dp[maxt][m];
return 0;
}