Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 3154 | Accepted: 907 |
Description
Your program will be given numbers and types of coins Charlie has and the coffee price. The coffee vending machines accept coins of values 1, 5, 10, and 25 cents. The program should output which coins Charlie has to use paying the coffee so that he uses as many coins as possible. Because Charlie really does not want any change back he wants to pay the price exactly.
Input
Output
Sample Input
12 5 3 1 2 16 0 0 0 1 0 0 0 0 0
Sample Output
Throw in 2 cents, 2 nickels, 0 dimes, and 0 quarters. Charlie cannot buy coffee.
題意:告訴你1、5、10、25單位金幣的數量和一個金幣值n,求所有用這些金幣組成這個n的方案中使用金幣最多的那個,分別輸出每種硬幣使用的數量
昨天我可是瞅了大半天都沒瞅出啥把戲出來啊,寫了好幾次,都是半路中間讓我糾結,所以去溜別個的博客採陰補陽去了,看到一個寫法跟我一樣,但是犀利了很多,比如最後查詢,巧妙的採用了 i 與 i-1 之間的差值,哎,是我太笨
解析:多重揹包,把金額作爲容量,也就是dp的下標,dp[x]中裝的是組成金額爲 x 的使用金幣數量的最大值,然後我用dis記錄前驅點,比如dp[x]=dp[x-v]+m,則dis[x]=x-v,
然後重要的是每次作用的金幣要在對應的dp[ ]數組中記錄這個點所在路徑上使用的數量
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int main (void)
{
int n,m,i,j,k,l,num[4],val[4]={1,5,10,25};
int dp[11111],dis[11111],v[11111];
int x[33];
while(~scanf("%d",&n))
{
if(n==0)k=1;
else k=0;
for(i=0;i<4;i++)
{
scanf("%d",&num[i]);
if(num[i])k=0;
}
if(k)break;
memset(dp,-1,sizeof(dp));
dp[0]=0;
memset(dis,0,sizeof(dis));
dis[0]=-1;
for(i=0;i<4;i++)
{
memset(v,0,sizeof(v));
for(j=val[i];j<=n;j++)
if(dp[j-val[i]]>=0&&v[j-val[i]]<num[i]&&dp[j]<dp[j-val[i]]+1)
{
dp[j]=dp[j-val[i]]+1; //使用金幣數量最大值
dis[j]=j-val[i]; //記錄前驅點,前驅點的金額加上這次裝入的金幣金額等於這次的金額
v[j]=v[j-val[i]]+1; //記錄 i 號金幣已經在這條路徑上使用的數量
}
}
if(dp[n]>0)
{
memset(x,0,sizeof(x));
i=n;
while(dis[i]>=0)
{
x[i-dis[i]]++; //dis中:a+金幣金額=b,所以金幣金額=b-a
i=dis[i]; //直接往記錄的前驅點跳躍
}
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",x[val[0]],x[val[1]],x[val[2]],x[val[3]]);
}else
{
puts("Charlie cannot buy coffee.");
}
}
return 0;
}
總結:我就記得01揹包跟完全揹包,然後腦子裏面還有一個多重揹包,我記得是數量從1到K一個一個去01揹包的,這個方法很耗時,然後是有個二進制壓縮的方法,使用2的0次方到n次方來進行完全揹包,這個是一般多重揹包通用的方案,這次不會寫多重了,畢竟很久沒動了,所以看了自己以前寫的,結果。。尼瑪,看懂了,卻發現這個題在使用的時候要考慮情況,就是沒有方案的時候不能疊加,哎,以後這做題不能停的,停一天可就要當一年的傻逼了