HDU 2844 Coins(多重背包)

一个多重背包问题,有一点儿不同的是状态转移方程式了,这里的dp存的不再是价值和了,而是一个bool值,代表的是dp[i]中能不能凑齐到i 的钱,和01背包很像,说明如下:

假如现在要新添一个银币j,问是否能够凑齐到钱 i .那么,如果现在需要凑齐的钱i  减去  硬币 j 的面值 的钱 为 i-A[j].cost,如果i-A[j].cost的钱依然能够凑齐,那么i 也必定能凑齐(这个不用解释吧)

  dp[i]=dp[i-A[j].cost]?true:false

然后就一样了

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int MAX =100005;
bool  dp[MAX];
int v;
int a[MAX],num[MAX];
void zeroOnePack(int cost ,int value)
{
	for(int i=v;i>=cost;i--)
		if(dp[i-cost]==true)
			dp[i]=true;
}
void completePack(int cost,int value)
{
	for(int  i=cost;i<=v;i++)
		if(dp[i-cost]==true)
			dp[i]=true;
}
void multiplePack(int cost,int value,int amount)
{
	if(cost*amount>=v)
	{
		completePack(cost,value);
		return ;
	}
	int k=1;
	while(k<amount)
	{
		zeroOnePack(k*cost,k*value);
		amount-=k;
		k*=2;
	}
	zeroOnePack(amount*cost,amount*value);
}
int main()
{
	int n;
	while(~scanf("%d%d",&n,&v),v,n)
	{
		memset(dp,false,sizeof(dp));
		dp[0]=true;
		for(int i=1;i<=n;i++)
			scanf("%d",&a[i]);
		for(int i=1;i<=n;i++)
			scanf("%d",&num[i]);
		for(int i=1;i<=n;i++)
			multiplePack(a[i],1,num[i]);
		int cnt=0;
		for(int i=1;i<=v;i++)
			if(dp[i])
				cnt++;
		printf("%d\n",cnt);
	}
	return 0;
}


你可能感兴趣的:(HDU 2844 Coins(多重背包))