编程中一类问题的求解用到母函数,在这里母函数相当于一个公式,遇到这类问题就套用母函数,就像高中的时候我们在做物理中速度一类题时,我们会用到加速度一类的公式。当然这里不仅仅是懂得母函数,还要了解如何用程序来实现母函数。网上有实现母函数模板,再做不同的题时需要根据模板去改进。所以,要想利用母函数做题,不仅仅只是记住模板,还要理解。
母函数的实现用到了动态规划的知识,所以如果对动态规划有一定了解的话,对模板的理解有很大的帮助。
这里以杭电1085 为例:
本.拉登要求用给定面值的钱及每种硬币的数量来寻找由这些硬币不能组成的最小面值。其实就是整数拆分的一种变体,不同的是硬币的数量;在整数拆分中,c1[i]记录了值i有多少种情况。而本题就想求出从1到n+1中最小的i,且c[i]等于0;(注意:为什么是到n+1?因为,有这些面值可能组成由1到n的所有值,所以n+1就成了不能构成的最小值)
源代码:#include <iostream>
using namespace std;
int main()
{
int i,j,k,n,a,b,c,x;
int c1[8001],c2[8001],t[2],s[2]={2,5};
while(cin>>a>>b>>c)
{
// x=0;
if(a==0&&b==0&&c==0)
break;
t[0]=b;
t[1]=c;
n=a+b*2+c*5;
for(i=0;i<=n;i++)
{c1[i]=0;c2[i]=0;}
for(i=0;i<=a;i++)
c1[i]=1;
//cout<<"1"<<endl;
for(i=0;i<2;i++)//表示分成的数值
{
for(j=0;j<=a+2*b;j++)
{//if(c1[j]!=0)
// {
x=0;
for(k=0;k<=t[i];k++)
{ c2[x+j]+=c1[j];x=x+s[i];}
// }
}
//cout<<"2"<<endl;
for(j=0;j<=n;j++)
{c1[j]=c2[j];c2[j]=0;}
}
//cout<<"4"<<endl;
for(i=1;i<=n;i++)
if(c1[i]==0)
{cout<<i<<endl;break;}
if(i==n+1)
cout<<n+1<<endl;
}
return 0;
}
以上程序和模板的构造是一样的!c1[],c2[]数组是必须存在的!
总共有三种硬币,1,2,5,而不是整数查分的从1到n;所以第二个横线循环是for(i=0;i<2;i++)只用到s[0]和是s[1].
在给c1[]赋值时,for(i=0;i<=a;i++)c1[i]=1;这里每个i都是由1组成。