【DP】分组背包

Description

有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。这些物品被划分为若干组,每组中的物品互相冲突,最多选一件。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。

Input

第一行:三个整数,v(背包容量,v<=200),n(物品数量,n<=30)和t(最大组号,t<=10);
第2…n+1行:每行三个整数wi,ci,p,表示每个物品的重量、价值、所属组号。

Output

仅一行,一个数,表示最大总价值。

Sample Input
10 6 3
2 1 1
3 3 1
4 8 2
6 9 2 
2 8 3
3 9 3
Sample Output
20

题意

与01背包差不多,就是其中一组东西中这能选一个

#include<iostream>
#include<cstdio>
using namespace std;
int a[1005],b[505],c[105],d[55][3],f[2005];
int n,m,t,l;
int e(int i,int j)//交换
{
	int tt;
	tt=a[i],a[i]=a[j],a[j]=tt;
	tt=b[i],b[i]=b[j],b[j]=tt;
	tt=c[i],c[i]=c[j],c[j]=tt;
}
int main()
{
	scanf("%d%d%d",&m,&n,&l);
	for(int i=1;i<=n;++i)
		scanf("%d%d%d",&a[i],&b[i],&c[i]);
	for(int i=1;i<=n;++i)//把同一组的排在一起
		for(int j=i+1;j<=n;++j)
			if(c[i]>c[j])e(i,j);//交换某评测机无法用swap()...
	int tt=1,kk=2,maxx=0x3f;
	d[1][0]=1;maxx=min(maxx,a[1]);
	while(kk<=n)//预处理
	{
		if(c[kk-1]==c[kk])
		{
			++d[tt][0];//同一组的个数加一
			maxx=min(maxx,a[kk]);//判断每一组中最小的
		}
		else 
		{
			d[tt][1]=maxx;//最小的
			d[tt][2]=d[tt-1][2]+d[tt][0];//从第几个开始
			d[++tt][0]++;//下一组个数加一
			maxx=a[kk];//下一组最小的先赋为一组中的第一个
		}
		++kk;
	}
	for(int i=1;i<=tt;++i)//for每一组
	{
		for(int j=m;j>=d[i][1];--j)//for重量从大到最小
		{
			for(int k=1;k<=d[i][0];++k)//for一组中的所有
				if(j>=a[d[i-1][2]+k])f[j]=max(f[j-a[d[i-1][2]+k]]+b[d[i-1][2]+k],f[j]);
		}
	}
	printf("%d",f[m]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_wujiajie/article/details/85169991