题意:问四种价值硬币是否能凑够某个值,并输出用最少硬币的。(硬币有个数限制)

题解:多重背包,先将要凑成的小数化为整形即可。

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 int dp[700];
 6 int pr[700];
 7 int main()
 8 {
 9     int a,b[5],c[5]={25,10,5,1},op[50];
10     char s[100];
11     op[25]=0;op[10]=1;op[5]=2;op[1]=3;
12     while(scanf(" %s %d %d %d %d",s,&b[0],&b[1],&b[2],&b[3])!=EOF)
13     {
14         memset(dp,-1,sizeof(dp));
15         dp[0]=0;
16         bool flag=false;
17         int pos;
18         for(int i=0;s[i]!='\0';i++)
19             if(s[i]=='.')
20             {
21                 pos=i;
22                 flag=true;
23                 break;
24             }
25         if(flag)
26         {
27             int x,y;
28             sscanf(s,"%d.%d",&x,&y);
29             if(y<10&&s[pos+1]!='0')
30                 y*=10;
31             a=x*100+y;
32         }
33         else
34             sscanf(s,"%d",&a);
35         for(int i=0;i<4;i++)
36         {
37             int v=c[i],n=b[i];
38             if(n*v>=a)
39                 for(int i=0;i+v<=a;i++)
40                 {
41                     if(dp[i]!=-1&&(dp[i+v]==-1||dp[i+v]>dp[i]+1))
42                         dp[i+v]=dp[i]+1,pr[i+v]=i;
43                 }
44             else
45             {
46                 while(n--)
47                 for(int i=a;i-v>=0;i--)
48                     if(dp[i-v]!=-1&&(dp[i]==-1||dp[i]>dp[i-v]+1))
49                         dp[i]=dp[i-v]+1,pr[i]=i-v;
50             }
51         }
52         if(dp[a]==-1)
53             puts("NO EXACT CHANGE");
54         else
55         {
56             int tot[4];
57             memset(tot,0,sizeof(tot));
58             for(int i=a;i!=0;tot[op[i-pr[i]]]++,i=pr[i]);
59             printf("%d %d %d %d\n",tot[0],tot[1],tot[2],tot[3]);
60         }
61     }
62     return 0;
63 }