//题意:给你面值是1,2,5的硬币的数量,要你求由这些硬币不能组成的最小的金额。。

下面给出3种方法;
//方法1:很明显母函数
//我这里一步一步的求。。
//下面是我的一点理解。。如果叫你写由面值1,2,5的硬币所组成的金额的母函数
//Y=(1+x^2+x^3+x^4…+x^n1*1)*(1+x^2+x^4+x^6…x^n2*2)*(1+x^5+x^10+…x^n3*5)
//这里要理解。。配合HDU 1085来理解。。

#include <iostream>
#include <stdio.h>
using namespace std;
int c1[10000],c2[10000];
int main()
{
 int i,j,k;
 int a,b,c;
 int sum=0;
 while(scanf("%d%d%d",&a,&b,&c)!=EOF)
 {
  if(a==0&&b==0&&c==0)break;
  sum=a+b*2+c*5;
  for(i=0;i<sum;i++)
  {
   c1[i]=0;
   c2[i]=0;
  }
  for(i=0;i<=a;i++)//第一个表达式。。(1+x^2+x^3+x^4…+x^n1*1)都取一个。。
   c1[i]=1;
  for(i=0;i<=a;i++)//先是面值1,和面值2,的硬币的母函数,。。就是第一个表达式乘第二个表达式;i控制的是第一个表达式指数。。j是第二个表达式的指数。。
   for(j=0;j<=b*2;j+=2)//j+=2..就是上面的Y=()()()的第一式子。。这样比较好理解
    c2[i+j]+=c1[i];//这步就是把指数相同的合并在一起,也就是把指数相同的系数相加。。[i+j]就是指数。。
   for(i=0;i<=a+b*2;i++)
   {
    c1[i]=c2[i];//把c2的赋值给c1.。
    c2[i]=0;
   }
   for(i=0;i<=a+b*2;i++)
    for(j=0;j<=c*5;j+=5)//和上面类似。。
     c2[i+j]+=c1[i];
    for(i=0;i<=a+b*2+c*5;i++)
    {
     c1[i]=c2[i];
     c2[i]=0;
    }
    for(i=0;i<=sum;i++)
    {
     if(c1[i]==0)
     {
      cout<<i<<endl;
      break;
     }
    }
    if(i==sum+1)
     cout<<i<<endl;
 }

 return 0;
}

//接下来是把分开的和起来。。
/*
#include <stdio.h>
#include <iostream>
using namespace std;
int a[8001],b[8001];
int c[]={1,2,5};
int main()
{
    int i,j,k,n[3],s;
    while(scanf("%d%d%d",&n[0],&n[1],&n[2])!=EOF,n[0]+n[1]+n[2])
    {
        s=n[0]*1+n[1]*2+n[2]*5;
        if(n[0]==0)
   printf("1\n");
        else
        {
   memset(a,0,sizeof(a));
   memset(b,0,sizeof(b));
            for(i=0;i<=n[0];i++)
                  a[i]=1;
            for(i=1;i<3;i++)
            {
    for(j=0;j<=s;j++)
                    for(k=0;k*c[i]+j<=s&&k<=n[i];k++)//k*c[i]+j<=s总的金额不能超过最大。k<=n[i] K是使用相应面值的数量 因此不能超过给定的上限 就是程序对应输入值   
                        b[k*c[i]+j]+=a[j];                
     for(j=0; j<=s; j++)
     {
      a[j]=b[j];
      b[j]=0;
     }
            }
            for(i=0; i<=s+1; i++)
                if(a[i]==0)
    {
     printf("%d\n",i);
     break;
    }
        }
    }
    return 0;
}*/
//方法2暴力法:
/*
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
 int a,b,c;
 int used[10000];
 while(scanf("%d%d%d",&a,&b,&c)!=EOF)
 {
  int ans=-1;
  memset(used,false,sizeof(used));
  if(a==0&&b==0&&c==0)break;
  for(int i=0;i<=a;i++)
   for(int j=0;j<=b;j++)
    for(int k=0;k<=c;k++)
     used[i*1+j*2+k*5]=true;
    for(i=1;i<=a+b*2+c*5;i++)
     if(used[i]==false)
      break;
   
     printf("%d\n",i);
 }
 return 0;
}*/

posted on 2011-08-11 11:27  →木头←  阅读(228)  评论(0编辑  收藏  举报