标签:
12 5 3 1 2
16 0 0 0 1
0 0 0 0 0
样例输出
Throw in 2 cents, 2 nickels, 0 dimes, and 0 quarters.
Charlie cannot buy coffee.
#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; #define met(a,b) (memset(a,b,sizeof(a))) #define N 11000 #define INF 0x3f3f3f3f int pre[N], v[5]={0,1,5,10,25}, dp[N]; int used[N]; /** dp[i] 代表组成i元时需要的最多的硬币 used[i] 代表第i种硬币用了几次(感觉这点很好,能将多重背包转化为完全背包) pre[j] 记录的是j从哪个状态转化过来的 */ int main() { int p, num[5]={0}; while(scanf("%d%d%d%d%d", &p, &num[1], &num[2], &num[3], &num[4]), p+num[1]+num[2]+num[3]+num[4]) { int i, j, ans[110]={0}; met(dp, -1); met(pre, -1); dp[0] = 0; for(i=1; i<=4; i++) { memset(used, 0, sizeof(used)); for(j=v[i]; j<=p; j++) { if(dp[j-v[i]]+1>dp[j] && dp[j-v[i]]>=0 && used[j-v[i]]<num[i]) { dp[j] = dp[j-v[i]]+1; used[j] = used[j-v[i]]+1; pre[j] = j-v[i]; } } } if(dp[p]<0) printf("Charlie cannot buy coffee.\n"); else { met(ans, 0); i = p; while(1) { if(pre[i]==-1) break; ans[i-pre[i]]++; i = pre[i]; } printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[v[1]], ans[v[2]], ans[v[3]], ans[v[4]]); } } return 0; }
(多重背包+记录路径)Charlie's Change (poj 1787)
标签:
原文地址:http://www.cnblogs.com/YY56/p/5539617.html