分组背包如何保证每组只取一个
必须从状态方程出发,已知分组背包问题的状态表示是
dp[i][j]: 考虑前i组,体积不超过j的情况下,能获得的最大值
当我们在更新第i组时,i本身没有变,只是将第i组所有元素遍历一遍,尝试更新本组的最大值,不会发生重复选择的情况,
给出一个实例,假定先选择了A,此时
dp[i][j] = dp[i - 1][j - v[a]] + w[a];
之后又发现B更好,就变成了
dp[i][j] = dp[i - 1][j - v[b]] + w[b];
此时dp[i][j]就会被b更新,且这次的更新不依赖之前选A产生的结果,只跟前i-1组的状态dp[i-1]相关,选择A产生的结果会被覆盖,因此保证了每组只选一个
#include<iostream>
using namespace std;
const int N = 110;
int v[N][N], w[N][N], s[N];
int dp[N][N];
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
cin >> s[i];
for(int j = 0; j < s[i]; j++)
cin >> v[i][j] >> w[i][j];
}
for(int i = 1; i <= n; i++)
for(int j = 0; j <= m; j++)
{
dp[i][j] = dp[i - 1][j];
for(int k = 0; k < s[i]; k++)
if(j >= v[i][k]) dp[i][j] = max(dp[i][j], dp[i-1][j-v[i][k]]+w[i][k]);
}
cout << dp[n][m];
}