分组背包
其实也不难,弄清楚01背包就十分好解决了!
题目描述:
有N件物品,告诉你这N件物品的重量以及价值,将这些物品划分为K组,每组中的物品互相冲突,最多选一件,求解将哪些物品装入背包可使这些物品的费用综合不超过背包的容量,且价值总和最大。
算法分析:
首先判断一个分组当中的一件物品,同01背包一样,此物品存在两种状态,取与不取,若取此物品,则继续判断下一组的第一件物品,若不取此物品,则继续判断本组下一件物品,若该物品为本组最后一件物品,则判断下一组。也就是说设f[k][v]表示前k组物品花费费用v能取得的最大价值。
二维:
f[i][C]=max{f[i-1][C],f[i-1][C-w[x]]+v[x]
{物品x属于组i}。
一维
f[C]=max{f[C],f[C-w[x]]+v[x]
{物品x属于组i}。
使用一维数组的伪代码如下:
for 所有的组k
for v=V..0
for 所有的i属于组k
f[v]=max{f[v],f[v-c[i]]+w[i]}
对于这种背包,我采用了vector(动态数组)。不懂戳这里
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e3+10;
vector<int>a[N];
int n,C,w[N],v[N],f[N],cnt,maxgroup;
int main()
{
//fre();
scanf("%d%d",&C,&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&w[i],&v[i],&cnt);
maxgroup=max(maxgroup,cnt);
a[cnt].push_back(i);
}
for(int i=1;i<=maxgroup;i++)
{
for(int j=C;j>=0;j--)
{
for(int k=0;k<a[i].size();k++)
{
int x=a[i][k];
if(j>=w[x]) f[j]=max(f[j],f[j-w[x]]+v[x]);
}
}
}
printf("%d",f[C]);
return 0;
}