首页 > 代码库 > UVa 674 & hdu 2069 Coin Change (母函数,dp)

UVa 674 & hdu 2069 Coin Change (母函数,dp)

链接:uva 674

题意:有5中货币,价值分别为 50-cent, 25-cent, 10-cent, 5-cent,1-cent,数量都为无限个,

给定一个数 n,求用上述货币组成价值为 n 的方法有多少?

分析:因为n<=7489,可以用 母函数 或 dp 打表

对于dp状态方程为: dp[j]+=dp[j-c[i]]

母函数:

#include<stdio.h>
int c1[7500],c2[7500],w[5]={1,5,10,25,50};;
void mhs()
{
    int i,j,k;
    for(i=0;i<=7489;i++){
        c1[i]=1;
        c2[i]=0;
    }
    for(i=1;i<5;i++){
        for(j=0;j<=7489;j++)
            for(k=0;j+k<=7489;k+=w[i])
                c2[j+k]+=c1[j];
        for(j=0;j<=7489;j++){
            c1[j]=c2[j];
            c2[j]=0;
        }
    }
}
int main()
{
    int n;
    mhs();
    while(scanf("%d",&n)!=EOF)
        printf("%d\n",c1[n]);
    return 0;
}

dp:

#include<stdio.h>
int dp[7500],c[5]={1,5,10,25,50};
int main()
{
    int n,i,j;
    dp[0]=1;
    for(i=0;i<5;i++)
        for(j=c[i];j<=7489;j++)
            dp[j]+=dp[j-c[i]];
    while(scanf("%d",&n)!=EOF)
        printf("%d\n",dp[n]);
    return 0;
}

链接:hdu 2069

这题咋一看去跟上一题一样,样例神马的都一样,心中窃喜,拿上一题代码之间复制粘贴,

结果瞬间就WA,顿时懵了,很忧伤、、、只得好好瞅瞅题了、、、

题意:这题也是有5种货币,分别为50-cent, 25-cent, 10-cent, 5-cent,1-cent,数量都为无限个,

给定一个数 n,要求用所给货币,求用不超过100个货币,组成价值为 n 的方法个数。

分析:这题只是比上题多了个所用货币数额的限制条件,因为n<=250,同样还是可以用母函数或dp打表做,

但是因为要记录用了多少个货币,要从一维扩展为二维,

母函数:

#include<stdio.h>
int c1[300][105],c2[300][105],s[300];
int w[5]={1,5,10,25,50};
void mhs()
{
    int i,j,k,p;
    for(i=0;i<=100;i++)
        c1[i][i]=1;
    for(i=1;i<5;i++){
        for(j=0;j<=250;j++)
            for(k=0;j+k*w[i]<=250;k++)
                for(p=0;k+p<=100;p++)    //限制所用货币不超过100
                    c2[j+k*w[i]][p+k]+=c1[j][p];
        for(j=0;j<=250;j++)
            for(p=0;p<=100;p++){
                c1[j][p]=c2[j][p];
                c2[j][p]=0;
            }
    }
    for(j=0;j<=250;j++)
        for(p=0;p<=100;p++)
            s[j]+=c1[j][p];
}
int main()
{
    int n;
    mhs();
    while(scanf("%d",&n)!=EOF)
        printf("%d\n",s[n]);
    return 0;
}

dp

#include<stdio.h>
int dp[105][300],c[5]={1,5,10,25,50};
int main()
{
    int n,i,j,k,s[300]={0};
    dp[0][0]=1;                  //0可以用0个货币组成,这也算一种方法
    for(i=0;i<5;i++)
        for(j=1;j<=100;j++)
            for(k=c[i];k<=250;k++)
                dp[j][k]+=dp[j-1][k-c[i]];
    for(i=0;i<300;i++)
        for(j=0;j<=100;j++)
            s[i]+=dp[j][i];  //求能用0-100组成价值为 i的总方法数
    while(scanf("%d",&n)!=EOF)
        printf("%d\n",s[n]);  
    return 0;
}