题意:分硬币,有1,5,10,25四种硬币,给定每种硬币的数量,给定要组合成的价值,问刚好达到价值时用的硬币最多的情况。
思路:dp[j] 表示 j 块钱最多由多少块硬币组成, used[j] 表示 j 块钱时,已经放了多少同种类的硬币。(实际上path用一维数组即可,使得 path[j] 表示 上一次最多有多少块构成的 j 块钱)
#include <cstdio>
#include <cstring>
#include <algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define N 10005
using namespace std;
int v[5],num[5],dp[N],p[5][N],res[5],used[N];
int m;
void print(int x,int y){
if(!x)
return;
res[x] = p[x][y];
print(x-1,y-p[x][y]*v[x]);
}
int main(){
v[1] = 1;
v[2] = 5;
v[3] = 10;
v[4] = 25;
while(scanf("%d",&m)){
int i,j;
for(i = 1;i<=4;i++)
scanf("%d",&num[i]);
if(!m)
break;
memset(dp, -1, sizeof(dp));
memset(res,0,sizeof(res));
memset(p, 0, sizeof(p));
dp[0] = 0;
for(i = 1;i<=4;i++){
memset(used,0, sizeof(used));
for(j = v[i];j<=m;j++)
if(used[j-v[i]]<num[i] && dp[j-v[i]]>=0 && dp[j-v[i]]+1>dp[j]){
dp[j] = dp[j-v[i]]+1;
used[j] = used[j-v[i]]+1;
p[i][j] = used[j];
}
}
if(dp[m]>=0){
print(4,m);
printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",res[1],res[2],res[3],res[4]);
}
else
printf("Charlie cannot buy coffee.\n");
}
return 0;
}