• POJ 3181 Dollar Dayz 【完全背包】


    题意:

    给出两个数,n,m,问m以内的整数有多少种组成n的方法
    完全背包+大数划分

    思路:

    dp[i][j] := 用i种价格配出金额j的方案数。

    那么dp[i][0] = 1,使用任何价格配出金额0的方案个数都是1(什么都不用)。

    递推关系式:

    实际上是完全背包问题,只是状态转移方程形式有所不同,不过状态转移的方向是完全相同的。

    dp[i][j] = dp[i – 1][j] + dp[i – 1][j – i] + dp[i – 1][j – 2 * i] + … + dp[i – 1][0]

    附: 01背包完全背包详解

    #include <iostream>
    #include <cstdio>
    #include <string.h>
    #include <string>
    #include <algorithm>
    using namespace std;
    
    unsigned long long a[105][1005],b[105][1005],inf=1;
    
    int main()
    {
        int n,m,i;
        for(int i=0;i<18;i++)
            inf*=10;
        while(~scanf("%d%d",&n,&m))
        {
            memset(a,0,sizeof(a));
            memset(b,0,sizeof(b));
            for(i = 0;i<=m;i++)
            {
                a[i][0] = 1;// 使用任何价格配出金额0的方案个数都是1
            }
            for(int i=1;i<=m;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(j<i)
                    {
                        a[i][j]=a[i-1][j];
                        b[i][j]=b[i-1][j];
                    }
                    else
                    {   // 处理大数前面的部位,当超过int64时,就开始存入b数组,因为in64是9.22..*10^18次方,保证了两个a想加必定不超过in64
                        b[i][j]=(b[i-1][j]+b[i][j-i])+(a[i-1][j]+a[i][j-i])/inf;
                        a[i][j]=(a[i-1][j]+a[i][j-i])%inf;//保留后面的部份
                    }
                }
            }
            if(b[m][n])
                printf("%lld",b[m][n]);
            printf("%lld
    ",a[m][n]);
        }
        return 0;
    }
  • 相关阅读:
    P1092 虫食算
    P1040 加分二叉树
    cfER76 abcd
    cf599 div2 a/b1/b2/c
    AtCoder Contest 144 DE
    Round G 2019
    luogu3084 Photo 单调队列优化DP
    luogu4234 最小差值生成树
    luogu1373 小a和uim之大逃离
    luogu1070 道路游戏 单调队列
  • 原文地址:https://www.cnblogs.com/demian/p/7368350.html
Copyright © 2020-2023  润新知