Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 3792 | Accepted: 1144 |
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四种硬币,给定每种硬币的数量,给定要组合成的价值,问刚好达到价值时用的硬币最多的情况。
附上代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define N 10010 5 #define inf (-0x3f3f3f3f) 6 using namespace std; 7 int max(int a,int b) 8 { 9 return a>b?a:b; 10 } 11 int main() 12 { 13 int dp[N],path[N],used[N]; 14 // dp[j] 表示 j 块钱最多由多少块硬币组成, 15 //path[j] 表示 上一次最多有多少块构成的 j 块钱,used[j] 表示 j 块钱时,已经放了多少同种类的硬币。 16 int i,j,m,n; 17 int num[4],val[4]= {1,5,10,25}; 18 while(~scanf("%d %d %d %d %d",&n,&num[0],&num[1],&num[2],&num[3])) 19 { 20 if(n==0&&num[0]==0&&num[1]==0&&num[2]==0&&num[3]==0) 21 break; 22 memset(dp,inf,sizeof(dp)); 23 memset(path,0,sizeof(path)); 24 path[0]=-1; 25 dp[0]=0; 26 27 for(i=0; i<4; i++) 28 { 29 memset(used,0,sizeof(used)); 30 for(j=val[i]; j<=n; j++) 31 { 32 if(dp[j-val[i]]+1>dp[j]&&dp[j-val[i]]>=0&&used[j-val[i]]<num[i]) 33 { 34 dp[j]=dp[j-val[i]]+1; 35 used[j]=used[j-val[i]]+1; 36 path[j]=j-val[i]; 37 } 38 } 39 } 40 41 int ans[100]; 42 memset(ans,0,sizeof(ans)); 43 if(dp[n]<0) 44 { 45 printf("Charlie cannot buy coffee.\n"); 46 } 47 else 48 { 49 while(path[n]!=-1) 50 { 51 ans[n-path[n]]++; 52 n=path[n]; 53 } 54 printf("Throw in %d cents, %d nickels, %d dimes, and %d quarters.\n", ans[val[0]], ans[val[1]], ans[val[2]], ans[val[3]]); 55 } 56 } 57 return 0; 58 }