zoukankan      html  css  js  c++  java
  • POJ 3181 Dollar Dayz(全然背包+简单高精度加法)

    POJ 3181 Dollar Dayz(全然背包+简单高精度加法)

    http://poj.org/problem?id=3181

    题意:

           给你K种硬币,每种硬币各自是1美元,2美元…K美元且能够无限使用,问你用上面K种硬币构成n美元的话有多少种方法?

    分析:

           本题是一道明显的全然背包问题, 只是本题还能够换一种方法来看: 整数n由前K个自然数构造, 一共同拥有多少种方法?

    (尽管本题要用到高精度加法, 可是非常easy, 不要被吓到哦)

     

    首先是DP部分:

           令dp[i][j]==x 表示由前i种硬币构成j美元一共同拥有x种方法.

           初始化dp全0 且 dp[0][0]=1

           状态转移: dp[i][j] = sum( dp[i-1][j] , dp[i][j-val[i]] )    //sum为求和,val[i]是第i种硬币的面值.

    前者表示第i种硬币一个都不选, 后者表示至少选一个第i种硬币来用.

           终于所求: dp[k][n]的值. 程序实现用的滚动数组, 所以dp仅仅有[j]一维.

     

    其次是高精度部分:

           假设输入1000 100时,输出将为:

             15658181104580771094597751280645这个值超过了long long的范围. 所以这里我们须要用大整数来表示dp[i][j]的值. 我的大整数实现是用high和low 的组合来表示一个大整数的. 当中low表示大整数的十进制表示时的低18位数. high表示大整数的十进制表示时的高18位数.

           整体来说实现比較简单.

    AC代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const long long BASE = 1e18;
    const int maxn=1000+5;
    
    int n,k;
    
    //大整数类
    class BigNum
    {
    public:
        BigNum(){}
        BigNum(long long high,long long low):high(high),low(low){}
        long long high; //高18位
        long long low;  //低18位
    
        //相加运算
        BigNum operator+(BigNum &B)
        {
            long long high_tmp = (low+B.low)/BASE+high+B.high;
            long long low_tmp = (low+B.low)%BASE;
            return BigNum(high_tmp, low_tmp);
        }
    
        //输出值
        void print()
        {
            if(!high)//高位为0
                printf("%I64d
    ",low);
            else     //高位非0
            {
                printf("%I64d",high);
                printf("%018I64d",low);
            }
        }
    }dp[maxn];
    
    int main()
    {
        while(scanf("%d%d",&n,&k)==2)
        {
            //初始化
            memset(dp,0,sizeof(dp));
            dp[0].low=1;//等效于令dp[0]=0;
    
            //递推
            for(int i=1;i<=k;i++)
            {
                for(int j=i;j<=n;j++)
                    dp[j] = dp[j]+dp[j-i];
            }
    
            //输出
            dp[n].print();
        }
    
        return 0;
    }
    

  • 相关阅读:
    多重平行中介(Mplus)
    小米手机,发短信出现闪退
    宇宙是有边还是没边?
    如何查一篇文章的引用文章
    卡方检验
    函数的形参与实参(二维数组)
    输出矩阵四周的数字的平均数(C)
    关于amos 的自由度
    Sql server case when then
    Sql Server中两个表之间数据备份和导入
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7242871.html
Copyright © 2011-2022 走看看