地址:http://poj.org/problem?id=1787
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 2689 | Accepted: 721 |
Description
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的四种硬币分别有c1、c2、c3、c4枚,问买一杯P元的咖啡最多用多少硬币。
思路:多重:因为只有四种硬币,所以用了十分暴力的记录路径的方法。
完全:模拟出来的,详细见代码。
代码:
多重背包:
#include
#include
#include
using namespace std;
int dp[10010][5]; //多开一维用来记录路径
int main()
{
int v,c[5],i;
int cent[5]= {0,1,5,10,25};
while(scanf("%d%d%d%d%d",&v,&c[1],&c[2],&c[3],&c[4])>0)
{
if(!v&&!c[1]&&!c[2]&&!c[3]&&!c[4]) break;
memset(dp,0,sizeof(dp));
for(int s=1; s<5; s++)
{
if(c[s]*cent[s]>=v)
{
for(i=cent[s]; i<=v; i++)
{
if(!(i==cent[s]||dp[i-cent[s]][0])) continue;
int k=max(dp[i][0],dp[i-cent[s]][0]+1);
if(k>dp[i][0])
{
dp[i][0]=k;
for(int j=1;j<=s;j++)
{
if(j==s) dp[i][j]=dp[i-cent[s]][j]+1;
else dp[i][j]=dp[i-cent[s]][j];
}
}
}
}
else
{
int m=1;
while(c[s])
{
c[s]-=m;
for(i=v; i>=m*cent[s]; i--)
if(i==m*cent[s]||dp[i-m*cent[s]][0])
{
int k=max(dp[i-m*cent[s]][0]+m,dp[i][0]);
if(k>dp[i][0])
{
dp[i][0]=k;
for(int j=1;j<=s;j++)
{
if(j==s) dp[i][j]=dp[i-m*cent[s]][j]+m;
else dp[i][j]=dp[i-m*cent[s]][j];
}
}
}
m=m<<1;
if(m>c[s]) m=c[s];
}
}
}
if(dp[v][0]) printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",dp[v][1],dp[v][2],dp[v][3],dp[v][4]);
else printf("Charlie cannot buy coffee.\n");
}
return 0;
} //因为是求最多的硬币数,所以dp[i][0]表示总硬币数,当总硬币数没变大时,就不用更新方案。(与01背包思想有点相似,都是保留相同体积的最优方案)
完全背包:
#include
#include
#include
using namespace std;
int dp[10010][2],used[10010];
int main()
{
int v,c[50],i,j;
int cent[5]= {0,1,5,10,25};
while(scanf("%d",&v)>0,v)
{
memset(dp,0,sizeof(dp));
for(i=1; i<=4; i++) scanf("%d",&c[i]);
for(i=1; i<=4; i++)
{
memset(used,0,sizeof(used));
for(j=cent[i]; j<=v; j++)
{
if(dp[j-cent[i]][0]+1>dp[j][0]&&(dp[j-cent[i]][0]||j==cent[i])&&used[j-cent[i]]+1<=c[i])
{
dp[j][0]=dp[j-cent[i]][0]+1; //根据总硬币数来更新最优结果
dp[j][1]=j-cent[i]; //记录路径
used[j]=used[j-cent[i]]+1; //判断硬币有没有用多
}
}
}
if(!dp[v][0]) printf("Charlie cannot buy coffee.\n");
else
{
c[1]=c[5]=c[10]=c[25]=0;
i=v;
while(i)
{
c[i-dp[i][1]]++; //根据路径来得出结果
i=dp[i][1];
}
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",c[1],c[5],c[10],c[25]);
}
}
return 0;
}