题目:http://acm.hdu.edu.cn/showproblem.php?pid=2069
题意:用1,5,10,,25,50面值的硬币组成n钱,求组合方案数【硬币总数不超过100】
法①:母函数,不过是注意有硬币总数限制,需要多一个循环,并用二维数组保存,c[ i ][ j ]表示用j个硬币组成i钱的方案数
法②:多个循环直接暴力
法①
#include<stdio.h>
#include<string.h>
#define MAX 250
#define LIMIT 100
int c[MAX+1][LIMIT+1],tc[MAX+1][LIMIT+1];
//c[i][j]:用j个硬币组成i钱的方案数,c[1][2]只代表用2个硬币时的情况,不是用1,2个硬币方案和
int main()
{
int i,j,k,l,n,res;
int cent[5] = {1,5,10,25,50}; //改半天死在这里了int cent[6] = {1,5,10,20,50};
memset(c,0,sizeof(c));
memset(tc,0,sizeof(tc));
for(i=0;i<=LIMIT;i++) //用i个硬币组成i钱只有1种情况
c[i][i] = 1;
for(i=1;i<5;i++)
{
for(j=0;j<=MAX;j++)
{
for(k=0;k+j<=MAX;k+=cent[i])
{
for(l=0;l+k/cent[i]<=LIMIT;l++)
{ //k/cent[i]代表当前要乘的这个硬币的个数
tc[j+k][l+k/cent[i]] += c[j][l];
} //更新当前价值的不同硬币数方案数
}
}
for(j=0;j<=MAX;j++) //重置
{
for(k=0;k<=LIMIT;k++)
{
c[j][k] = tc[j][k];
tc[j][k] = 0;
}
}
}
while(~scanf("%d",&n))
{
res = 0;
for(i=0;i<=LIMIT;i++)
res += c[n][i];
printf("%d\n",res);
}
return 0;
}
法②:
#include<stdio.h>
int main(){
int i,j,k,l,m,n;
int count[251]={0};
for(n=0;n<=250;n++)
for(j=0;j*5<=n;j++)
for(k=0;k*10<=n;k++)
for(l=0;l*25<=n;l++)
for(m=0;m*50<=n;m++){
i = n-5*j-10*k-25*l-50*m;
if( i>=0 && i+j+k+l+m<=100 ) //i>=0
count[n]++;
}
while(~scanf("%d",&n))
printf("%d\n",count[n]);
return 0;
}