HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包)

题目地址:点击打开链接

思路:看本博客背包类Tianyi Cui大神写的背包九讲,以及代码后的解释

AC代码:

#include<stdio.h>
#include<string.h>

int p[120],h[120],c[120],v[120];
int n,m;

int max(int a,int b)
{
	return a > b ? a : b;
}

void zeroone_pack(int money,int weight)
{
	int i;
	for(i=n; i>=money; i--)
	{
		v[i] = max(v[i],v[i-money] + weight);
	}
}

void complete_pack(int money,int weight)
{
	int i;
	for(i=money; i<=n; i++)
	{
		v[i] = max(v[i],v[i-money] + weight);
	}
}

void multi_pack()
{
	int i,count,k;
	for(i=0; i<m; i++)
	{
		if(p[i] * c[i] >= n)//这个种类的大米可以取到背包满,所以转化为完全背包
		{
			complete_pack(p[i],h[i]);
		}
		else//转化为01背包
		{
			k = 1;
			count = c[i];
			//while(k < n)
			//while(k < c[i])以后还要用c[i]的值进行运算,所以这个判断错误
			while(k < count)//看最后面注释
			{
				zeroone_pack(k*p[i],k*h[i]);
				count -= k;
				k *= 2;
			}
			zeroone_pack(count*p[i],count*h[i]);
		}
	}
	printf("%d\n",v[n]);
}

int main()
{
	int t,i;
	scanf("%d",&t);
	while(t--)
	{
		memset(v,0,sizeof(v));
		scanf("%d%d",&n,&m);
		for(i=0; i<m; i++)
		{
			scanf("%d%d%d",&p[i],&h[i],&c[i]);//注意有重名的情况
		}
		multi_pack();
	}
	return 0;
}

k=1 count=13
  count=12
k=2 count=12
  count=10
k=4 count=10
  count=6
k=8 count=6
  退出循环
假设count是13,则这个循环将物品分为1.2.4.6这四个物品,而这四个物品的任意组合情况可以得到1-13这种物品的所有取值情况

你可能感兴趣的:(HDU 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(多重背包))