题目:
分析:
分组背包
n , m
n 物品组
m 背包体积
每组物品里面, 有多种物品,(每种物品只有一件)给出每组物品里, 每件物品的价值, 体积
求 从 n 组物品中选, 每组物品最 多选一件物品, 也可以不选
总体积不超过 m , 总价值最大
f[i, j] = k;
1. 集合
表示: n 组物品中选, 每组物品最 多选一件物品, 也可以不选
总体积不超过 m 的所有选法的集合
(属性, 数)存的数是这个集合中的某一个方案, 这个方案总价值最大max(价值)
2. 计算集合
f[i, j] ---> 包含的子集, 只要找 到所有子集取 Max
在这个题里面, 每个子集就是一种方案
max(1, 2, 3, 4, ...i);
f[i, j]
不选 第 i 组的物品
f[i, j] = max(f[i, j], f[i - 1, j])
选 第 i 组的物品
选第 i 组的哪一个物品
k: 第 i 组 物品中第 k 个物品
f[i, j] = max(f[i - 1, j - vik] + wik, f[i, j])
f[i,j] = max(f[i-1,j], f[i-1,j-vi1]+wi1, f[i-1,j-vi2] +wi2...f[i-1,j-vik] + wik)
f[i,j-vi1] = max(f[i-1,j-vi1],f[i-1,j-2vi1]+wi1, f[i-1,j-vi1-vi2]+wi2...f[i-1,j-vi1-vik]+wik)
3. 边界: f[0, j] = 0;
4. O(n^3)
代码:
#include <iostream>
using namespace std;
const int N = 110;
int n, m;
int f[N][N];
int s[N], v[N][N], w[N][N];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++ )
{
cin >> s[i];
for (int j = 1; j <= s[i]; j ++ )
cin >> v[i][j] >> w[i][j];
}
for (int i = 1; i <= n; i ++ ) // 物品组
for (int j = 1; j <= m; j ++ ) // 体积
{
f[i][j] = f[i - 1][j];
for (int k = 1; k <= s[i]; k ++ ) // 每组物品中的每个物品
if (v[i][k] <= j)
f[i][j] = max(f[i - 1][j - v[i][k]] + w[i][k], f[i][j]);
}
cout << f[n][m] << endl;
return 0;
}
学艺不精,寥寥草草;