【9920】打包

Time Limit: 1 second
Memory Limit: 128 MB

【问题描述】

你现在拿到了许多的礼物,你要把这些礼物放进袋子里。你只有一个最多装下V 体积物品的袋子,你不能全部放进去。你也拿不动那
么重的东西。你估计你能拿的最大重量为 G。现在你了解了每一个物品的完美值、重量和体积,你当然想让袋子中装的物品的完美值
总和最大,你又得计划一下了。

【输入格式】

第一行:V 和 G 表示最大重量和体积。
第二行:N 表示拿到 N 件礼物。
第三到N+2行:每行3个数 Ti Vi Gi 表示各礼物的完美值、重量和体积

对于20%的数据 N,V,G,Ti,Vi,Gi≤10
对于50%的数据 N,V,G,Ti,Vi,Gi≤100
对于80%的数据 N,V,G,Ti,Vi,Gi≤300
80%到100%的数据是N,V,G,Ti,Vi,Gi≤380 的离散随机数据。

【输出格式】

输出共一个数,表示可能获得的最大完美值。

Sample Input

6 5

4

10 2 2

20 3 2

40 4 3

30 3 3


Sample Output

50

【题解】

二维费用的0/1背包。

给0/1背包的f数组增加一维

f[i][j]表示花费1不超过i,花费2不超过j所能获得的最大完美值

f[i][j] = max(f[i][j] , f[i-w1[m]][j-w2[m]]+ c[m]);

记住0/1背包是逆序更新的就好了。

【代码】

#include <cstdio>
#include <cstring>

int mw1,mw2,n,c[400],w1[400],w2[400],f[400][400];

void input_data()
{
	scanf("%d%d",&mw1,&mw2);
	scanf("%d",&n);
	for (int i = 1;i <= n;i++)
		scanf("%d%d%d",&c[i],&w1[i],&w2[i]); //输入有两个花费的物品的信息 
}

void get_ans()
{
	memset(f,0,sizeof(f)); //初始化f数组为0 
	for (int i = 1;i <= n;i++)
		for (int j = mw1;j>=w1[i];j--) //枚举花费1和花费2  因为都是01背包所以都逆序。 
			for (int k = mw2;k >=w2[i];k--)
				if (f[j][k] < f[j-w1[i]][k-w2[i]] + c[i]) //如果能更新就更新 
					f[j][k] = f[j-w1[i]][k-w2[i]] + c[i];	
}

void output_ans()
{
	printf("%d",f[mw1][mw2]);
}

int main()
{
	//freopen("F:\\rush.txt","r",stdin);
	input_data();
	get_ans();
	output_ans();
	return 0;
}


posted @ 2017-10-06 19:23  AWCXV  阅读(180)  评论(0编辑  收藏  举报