dp[j] 表示 j 块钱最多由多少块硬币组成, prev[j] 表示 上一次最多有多少块构成的 j 块钱, used[j] 表示 j 块钱时,已经放了多少同种类的硬币。
AC代码如下:
#include <iostream>
#include <cstdio>
using namespace std;
int main(){
int P, dp[10001];
int prev[10001], used[10001];
int num[4];
int val[] = { 1, 5, 10, 25 };
while( 1 ){
cin >> P;
for( int i = 0; i < 4; i++ ){
cin >> num[i];
}
if( P == 0 && num[0] == 0 && num[1] == 0 && num[2] == 0 && num[3] == 0 ){
break;
}
memset( dp, -1, sizeof( dp ) );
dp[0] = 0;
prev[0] = -1;
for( int i = 0; i < 4; i++ ){
memset( used, 0, sizeof( used ) );
for( int j = val[i]; j <= P; j++ ){
if( dp[j-val[i]] + 1 > dp[j] && dp[j-val[i]] >= 0 && used[j-val[i]] < num[i] ){
dp[j] = dp[j-val[i]] + 1;
used[j] = used[j-val[i]] + 1;
prev[j] = j - val[i];
}
}
}
int ans[26];
memset( ans, 0, sizeof( ans ) );
if( dp[P] < 0 ){
cout << "Charlie cannot buy coffee." << endl;
}else{
while( prev[P] != -1 ){
ans[P-prev[P]]++;
P = prev[P];
}
printf( "Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[1], ans[5], ans[10], ans[25] );
}
}
return 0;
}