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.
Source
#include <iostream> #include <sstream> #include <ios> #include <iomanip> #include <functional> #include <algorithm> #include <vector> #include <string> #include <list> #include <queue> #include <deque> #include <stack> #include <set> #include <map> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <climits> #include <cctype> using namespace std; #define XINF INT_MAX #define INF 0x3F3F3F3F #define MP(X,Y) make_pair(X,Y) #define PB(X) push_back(X) #define REP(X,N) for(int X=0;X<N;X++) #define REP2(X,L,R) for(int X=L;X<=R;X++) #define DEP(X,R,L) for(int X=R;X>=L;X--) #define CLR(A,X) memset(A,X,sizeof(A)) #define IT iterator typedef long long ll; typedef pair<int,int> PII; typedef vector<PII> VII; typedef vector<int> VI; //const int MAXN = 10010; //#define INF 0x3FFFFFFF /************************************* **************头文件***************** *************************************/ int dp[10010];//dp[i]表示当费用为i时最多的硬币个数 int path[10010];//巧妙的记录路径 int used[10010];//某种货币已经使用的次数 int w[4] = {1,5,10,25};//4种货币 int ans[28];//答案,根据代码应该大于25 int main() { int P,a[5]; while(cin>>P) { REP(i,4) cin>>a[i]; if(P==0&&a[0]==0&&a[1]==0&&a[2]==0&&a[3]==0)break; //memset(dp,-INF,sizeof(dp)); for(int i = 0;i<=P;i++) dp[i] = -INF;//随意的设置为任何小于0的数,初始化 memset(path,0,sizeof(path));//初始化路径 dp[0] = 0;//当金额为0时,花费硬币个数为0 REP(i,4) { memset(used,0,sizeof(used));//每一次大循环都要更新来表示每一次钱币用到的个数; //used[j]表示到那个货币为j时用得到的i种货币的数量 for(int j = w[i];j<=P;j++)//这一重循环在学背包问题的时候大家都已经接触过 { if(dp[j]<dp[j-w[i]]+1&&dp[j-w[i]]>=0&&used[j-w[i]]<a[i]) { //////要注意的是dp[j]的上一个状态是dp[j-w[i]]不是dp[i-1] dp[j] = dp[j-w[i]]+1; used[j] = used[j-w[i]]+1;// path[j] = j-w[i];//具体的路径是怎么标记得最好做一遍单步调试,会更容易理解,近似于模拟指针 } //w[i] = j-path[j]这是导出下面ans的原理 } } memset(ans,0,sizeof(ans));//给答案初始化,实际上只用到ans[1],ans[5],ans[10],ans[25] if(dp[P] <0)//如果dp[P]依旧小于零就说明上面遍历时没有用到,就不能表示出来 { cout<<"Charlie cannot buy coffee."<<endl; continue; } else //下面的东西只要模拟一边或者但不调试一下很容易明白 { int i = P; while(1) { if(i==0) break; ans[i-path[i]]++; i = path[i]; } /*REP(i,P) { cout<<dp[i]<<" ";//大家可以把它加到代码里有助于理解 } cout<<endl; REP(i,P) { cout<<path[i]<<" "; }*/ cout<<"Throw in "<<ans[1]<<" cents, "<<ans[5]; cout<<" nickels, "<<ans[10]<<" dimes, and "; cout<<ans[25]<<" quarters."<<endl; } //0012341234567这是样例一中path的结果 } return 0; }