POJ 3181 Dollar Dayz 完全背包求方法总数+高精度大数类

Dollar Dayz

Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other)

Total Submission(s) : 6   Accepted Submission(s) : 3

Problem Description

Farmer John goes to Dollar Days at The Cow Store and discovers an unlimited number of tools on sale. During his first visit, the tools are selling variously for $1, $2, and $3. Farmer John has exactly $5 to spend. He can buy 5 tools at $1 each or 1 tool at $3 and an additional 1 tool at $2. Of course, there are other combinations for a total of 5 different ways FJ can spend all his money on tools. Here they are:

        1 @ US$3 + 1 @ US$2


        1 @ US$3 + 2 @ US$1


        1 @ US$2 + 3 @ US$1


        2 @ US$2 + 1 @ US$1


        5 @ US$1

Write a program than will compute the number of ways FJ can spend N dollars (1 <= N <= 1000) at The Cow Store for tools on sale with a cost of $1..$K (1 <= K <= 100).

 

 

Input

A single line with two space-separated integers: N and K.

 

 

Output

A single line with a single integer that is the number of unique ways FJ can spend his money.

 

 

Sample Input

5 3

 

 

Sample Output

5

 

 

Source

PKU

算法分析:
题意: 

有m种硬币,每种硬币分别是 1美元,2美元…m美元且可以无限使用,问你用上面m种硬币构成n美元的话有多少种方法?

分析:

       本题是一道明显的完全背包问题, 不过本题还可以换一种方法来看: 整数n由前K个自然数构造, 一共有多少种方法?

 

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-v[i]] )   //sum为求和,v[i]是第i种硬币的面值.

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

       最终所求: dp[k][n]的值.

 程序实现用的滚动数组, 所以dp只有[j]一维.

代码实现:

#include<cstdio>  
#include<cstring>  
#include<cstdlib>  
#include<cctype>  
#include<cmath>  
#include<iostream>  
#include<sstream>  
#include<iterator>  
#include<algorithm>  
#include<string>  
#include<vector>  
#include<set>  
#include<map>  
#include<stack>  
#include<deque>  
#include<queue>  
#include<list>  
using namespace std;  
const double eps = 1e-8;  
typedef long long LL;  
typedef unsigned long long ULL;  
const int INT_INF = 0x3f3f3f3f;  
const int INT_M_INF = 0x7f7f7f7f;  
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;  
const LL LL_M_INF = 0x7f7f7f7f7f7f7f7f;  
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};  
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1}; 
const long long BASE = 1e18; 
const int MOD = 1e9 + 7;  
const double pi = acos(-1.0);  
const int MAXN = 1e5 + 10;  
const int MAXT = 10000 + 10;  
const int M=1005;
using namespace std;
 
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\n",low);
        else     //高位非0
        {
            printf("%I64d",high);
            printf("%018I64d",low);
        }
    }
}dp[M];
 
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        //初始化
        memset(dp,0,sizeof(dp));
        dp[0].low=1;      //等效于令dp[0]=1;
 
        //递推,滚动数组优化
        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;
}

猜你喜欢

转载自blog.csdn.net/sdz20172133/article/details/81209689
今日推荐