分组背包和01背包结合求解,和多重背包相互区别!
区别:多重背包是一组物品可以选多件,而分组背包是每组物品只能选一件,且件件不一样。
结合:01背包是每组物品选或者不选,而分组背包是每组选一件,件件不一样,等效于在一组内,做01背包!
朴素版本:
#include<iostream>
using namespace std;
const int N = 1e2 + 10;
int v[N][N], w[N][N], s[N];
int f[N][N]; //从前i组物品里选,总体积不超过j的物品的最大价值!
int main()
{
int n, m;
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 ++) //前i组物品!
{
for (int j=0; j <= m; j ++) //枚举不同体积所能装载物品的最大值
{
f[i][j] = f[i-1][j]; //第 i 组物品不选!
for (int k=1; k <= s[i]; k ++) //在第i组里做01背包,第i组里面的物品只有s[i]件![
if (j >= v[i][k])
f[i][j] = max(f[i][j], f[i-1][j - v[i][k]] + w[i][k]);
}
}
cout << f[n][m] << endl;
return 0;
}
优化版:
#include<iostream>
using namespace std;
const int N = 1e2 + 10;
int f[N]; //滚动数组优化!
int v[N][N], w[N][N], s[N];
int main()
{
int n , m;
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=m; j >= 0; j --)
{
for (int k=0; k <= s[i]; k ++) //k=0表示第i组一件物品不选 === 不选第i组,这种情况必须枚举到,所以k从0开始!
{
if (j >= v[i][k]) //在分组背包里这里必须有
f[j] = max(f[j], f[j-v[i][k]] + w[i][k]);
}
}
}
cout << f[m] << endl;
return 0;
}