标签:
Description
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.
大意:给你一些钱,以及1.5.10.25零钱的个数,问你是否能拆开,并求出最多的分成的零钱的情况
第一次发现完全背包也能解决这种有限制的问题,一直以为只能在多重背包里面才能,原来用个if条件判断当前的num是否超过了t[i]就行
1.完全背包做法
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int v[5] = {0,1,5,10,25}; int dp[10010],ans[10010],num[10010],path[10010],t[5]; int p; int main() { while(~scanf("%d",&p)){ for(int i = 1; i <= 4; i++) scanf("%d",&t[i]); if((p+t[1]+t[2]+t[3]+t[4]) == 0) break; memset(dp,0,sizeof(dp)); memset(ans,0,sizeof(ans)); memset(path,0,sizeof(path)); dp[0] = 1; for(int i = 1; i <= 4; i++){ memset(num,0,sizeof(num)); for(int j = v[i]; j <= p; j++){ if(dp[j-v[i]] && dp[j-v[i]] + 1 > dp[j] && num[j-v[i]] < t[i]){ dp[j] = dp[j-v[i]] + 1;//使得后面每一个状态都是从前面一个得到,并且满足两个条件1:用去一个后的数目要比没用去的多2:用去的硬币数目不超过硬币本身 num[j] = num[j-v[i]] + 1; path[j] = j - v[i];//难想到。。用来记录路径 } } } int i = p; if(dp[p]>0){ while(i!=0){ ans[i-path[i]]++;//i-path[i] = i - ( i - v[i]) = v[i] i = path[i];//path[i]表示有i钱的时候用了一种硬币之后的钱的数目 } printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n",ans[1],ans[5],ans[10],ans[25]); } else printf("Charlie cannot buy coffee.\n"); } return 0; }
2.
POJ1787——背包DP(特定状态+回溯)——Charlie's Change
标签:
原文地址:http://www.cnblogs.com/zero-begin/p/4467281.html