这题是分组背包的改良版,如果还按分组背包的思路枚举每组物品状态会TLE
因此需要换一种思考方式
类似于状态机模型
状态表示
f[i]
表示前i-1
里任意选,但是选第i
个物品的最大价值
g[i]
表示前i个物品里边任意选的最大价值
每次弄人f[i]
里边放了第i
个物品,把物品的分组跑一边01背包
然后用来更新g[i]
这里的f[i]起到工具人的作用
状态转移方程:
f[j]=max(f[j],f[j-v]+w)
g[j]=max(g[j],f[j-price])
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int N=100010;
int f[N],g[N];
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int price,cnt;
cin>>price>>cnt;
memcpy(f,g,sizeof g);
while(cnt--)
{
int v,w;
cin>>v>>w;
for(int j=m;j>=v;j--)
f[j]=max(f[j],f[j-v]+w);
}
for(int j=m;j>=price;j--)g[j]=max(g[j],f[j-price]);
}
cout<<g[m]<<endl;
}