分组背包问题分析:
完全背包是枚举第 i
种物品选几个,分组背包是枚举第 i
组物品选哪个(或不选)
转移方程:dp[i,j]=max(dp[i-1,j],dp[i-1,j-v[i,k]]+w[i,k])
优化后:dp[j]=max(dp[j],dp[j-v[i,k]]+w[i,k])
时间复杂度:
O ( n m s ) O(nms) O(nms)
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int v[N][N], w[N][N];
int s[N];
int dp[N];
int n, m;
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=m;j>=0;--j)//转移方程运用的上一层,从大到小枚举体积
{
for(int k=1;k<=s[i];++k)//每组物品只能选一个或不选
{
//第i组物品中的第k个物品体积不可超过背包容量
if(v[i][k]<=j) dp[j] = max(dp[j], dp[j-v[i][k]]+w[i][k]);
}
}
}
cout<<dp[m]<<endl;
return 0;
}