POJ 2581

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

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

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 }

你可能感兴趣的:(poj)