【题目链接】
【解题思路】
和题目名一样,本题就是一道分组背包的模板题,我来讲一下分组背包。
其实就是先将说有的数据按照题意分组,再做01背包即可。
【CODE】
#include<iostream>
using namespace std;
int n,m,maxn;
struct name
{
int x,y,z;
}a[10100];
name G[1010][1010];//G[i][j]代表第i组的第j个
int num[1010];//num[i]代表第i组的元素个数
int d[10100];//01背包
int main()
{
cin>>n>>m;
for (int i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].y>>a[i].z;
//实现一个分组的操作
num[a[i].z]++;
G[a[i].z][num[a[i].z]].x=a[i].x;
G[a[i].z][num[a[i].z]].y=a[i].y;
maxn=max(a[i].z,maxn);//总组数
}
for (int i=1;i<=maxn;i++)//比01多一重第几组的循环
for (int j=n;j>=0;j--)//每组都只能选一个,如果完全按照01大会多选,所以要将这两重循环反过来
for (int k=1;k<=num[i];k++)
if (j>=G[i][k].x)//把判断条件移到这里来
d[j]=max(d[j],d[j-G[i][k].x]+G[i][k].y);//01背包
cout<<d[n];
return 0;
}
【后置知识】
我们所知的所有背包都是可以转化成01背包来做的。
例如:
完全背包
10
2 3 4
我们可以将其转化成
10
2 2 2 2 2 3 3 3 4 4
来做01背包。
但是当背包容量很大时,我们会发现这样子的效率太低了。
怎么办呢?
我们可以利用二进制优化。
例如:
100
1
我们拆的时候可以拆成
100
1 2 4 8 16 32 37
这样我们也可以用这 7 7 7 个数,来表示 1 1 1 到 100 100 100 的所有数,大大提升了01背包的效率。