題意:求經過c1個1分的c2個5分的c3個10分的c4個25分的組成p的最多個數而且輸出分別選多少個。ios
分析:多重揹包+一個數組保存當前最優解狀況下選的個數;數組
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> #include <cstdlib> #include <map> #include <vector> using namespace std; const int oo = 1e8; struct C { int x, num; }c[120]; void Init(int c1, int x, int &k) { int num = 1; while(c1>=num) { c[k].x = num*x; c[k++].num = num; c1-=num; num*=2; } if(c1!=0) { c[k].x = c1*x; c[k++].num = c1; } } bool cmp(C x1, C x2) { return x1.x < x2.x; } int dp[10005]; int ans[10005][6]; int main() { int p, c1, c2, c3, c4; while(scanf("%d %d %d %d %d", &p, &c1, &c2, &c3, &c4), p+c1+c2+c3+c4) { int k = 0; Init(c1, 1, k); Init(c2, 5, k); Init(c3, 10, k); Init(c4, 25, k); sort(c, c+k, cmp); memset(dp, 0, sizeof(dp)); memset(ans, 0, sizeof(ans)); dp[0] = 1; for(int i=0; i<k; i++) { for(int j=p; j>=c[i].x; j--) { if(dp[j-c[i].x]&&dp[j-c[i].x]+c[i].num > dp[j]) { dp[j] = dp[j-c[i].x]+c[i].num; int x = c[i].x/c[i].num; if(x==1) { ans[j][1] = ans[j-c[i].x][1]+c[i].num; ans[j][2] = ans[j-c[i].x][2]; ans[j][3] = ans[j-c[i].x][3]; ans[j][4] = ans[j-c[i].x][4]; } else if(x==5) { ans[j][2] = ans[j-c[i].x][2]+c[i].num; ans[j][1] = ans[j-c[i].x][1]; ans[j][3] = ans[j-c[i].x][3]; ans[j][4] = ans[j-c[i].x][4]; } else if(x==10) { ans[j][3] = ans[j-c[i].x][3]+c[i].num; ans[j][2] = ans[j-c[i].x][2]; ans[j][1] = ans[j-c[i].x][1]; ans[j][4] = ans[j-c[i].x][4]; } else { ans[j][4] = ans[j-c[i].x][4]+c[i].num; ans[j][2] = ans[j-c[i].x][2]; ans[j][3] = ans[j-c[i].x][3]; ans[j][1] = ans[j-c[i].x][1]; } } } } if(dp[p]==0) printf("Charlie cannot buy coffee.\n"); else printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[p][1], ans[p][2], ans[p][3], ans[p][4]); } return 0; }