题目链接:https://www.luogu.com.cn/problem/P1757
b就是在01背包的基础上对每个物品添加了组数,就变成了分组背包。
考虑到01背包的状态转移方程dp[j]=max(dp[j],dp[j-a[i]]+b[i]),分组背包和它相同.
那么怎么填这个表呢,在01背包中,通过俩层for循环来实现,第一层for是控制第i到n个拿不拿,在分组背包中,这个问题就变成了第i个到n组拿不拿。然后套01背包就可以了。
简单写就是for(i,num)//第1组到第num组
for(,)//01背包
for(,)
需要注意的是确定每个物品的位置,所以需要开个二维数组来存,f[第几组][第几个]
#include <bits/stdc++.h> #define inf 0x3f3f3f3f #define INF 0x7fffffffffffffff typedef long long ll; const double PI=3.1415926535897931; const long long mod=1e9+7; const int MA= 1e7+10; const int ma= 2*1e6+10; const int few=1e3+10; using namespace std; ////////////////////////////////////////////// int dp[ma]; int a[ma]; int b[ma]; int c[ma]; int f[few][few]; int num; int cnt[ma]; int main() { int m,n; cin>>m>>n; for(int i=1; i<=n; i++) { cin>>a[i]>>b[i]>>c[i]; num=max(num,c[i]);//找最大的组数 cnt[c[i]]++;统计每个组的数 f[c[i]][cnt[c[i]]]=i;记录成员的位置,方便后面的访问 } for(int k=1; k<=num; k++)//第1组到第num组 for(int j=m; j>=0; j--)//01背包 for(int i=1; i<=cnt[k]; i++) { int tmp=f[k][i]; if(j>=a[tmp]) dp[j]=max(dp[j],dp[j-a[tmp]]+b[tmp]);//熟悉的状态转移方程 } cout<<dp[m]<<endl; return 0; }