给出价格P,和五种硬币的数量,求最多 用多少个硬币组成P。
多重背包的应用,需要注意的是要统计每种硬币用了多少种,用father数组记录j(价格)是由哪个得到的。num数组表示此时有多少个硬币。
代码:
#include <stdio.h>
#include <string.h>
int dp[10010];
int p,c[5],ans[6],w[6]={0,1,5,10,25};
int father[10003],num[10003];
int mulity(int weight,int amount)
{
if(weight*amount>=p)
{
for(int j=weight;j<=p;j++)
{
if(dp[j-weight]!=-1&&dp[j]<dp[j-weight]+1)
{
dp[j]=dp[j-weight]+1;
father[j]=j-weight;
num[j]=1;
}
}
}
else
{
int k=1;
while(k<amount)
{
for(int i=p;i>=k*weight;i--)
{
if(dp[i-k*weight]!=-1&&dp[i]<dp[i-k*weight]+k)
{
dp[i]=dp[i-k*weight]+k;
father[i]=i-k*weight;
num[i]=k;
}
}
amount-=k;
k+=k;
}
for(int i=p;i>=amount*weight;i--)
{
if(dp[i-amount*weight]!=-1&&dp[i]<dp[i-amount*weight]+amount)
{
dp[i]=dp[i-amount*weight]+amount;
father[i]=i-amount*weight;
num[i]=amount;
}
}
}
}
int main()
{
while(scanf("%d %d %d %d %d",&p,&c[1],&c[2],&c[3],&c[4])!=EOF)
{
if(p+c[1]+c[2]+c[3]+c[4]==0)
break;
memset(dp,-1,sizeof(dp));
dp[0]=0;
memset(father,-1,sizeof(father));
memset(ans,0,sizeof(ans));
for(int i=1;i<=4;i++)
{
mulity(w[i],c[i]);
}
if(dp[p]==-1)
printf("Charlie cannot buy coffee.\n");
else
{
for(int i=p;i!=0;i=father[i])
{
int k=(i-father[i])/num[i];
for(int j=1;j<=4;j++)
{
if(k==w[j])
ans[j]+=num[i];
}
}
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",ans[1],ans[2],ans[3],ans[4]);
}
}
return 0;
}