POJ3181--Dollar Dayz(动态规划)

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


完全背包+高精度数

没有优化直接wa,是数值范围太小
#include<iostream>
using namespace std;
int dp[105][1005];
int main(){
    int n,k;
    cin>>n>>k;
    dp[0][0]=1;
    for(int i=1;i<=k;i++){
        for(int j=0;j<=n;j++){
            for(int k=0;k*i<=j;k++){
                dp[i][j]+=dp[i-1][j-k*i];
            }
        }
    }
    cout<<dp[k][n];
    return 0;
} 

 改用unsigned long long还是wa。那就用两个unsigned long long一个存低位一个存高位。unsigned long long的范围是1844674407370955161,所以用一个比它小一个数量级的数,

100000000000000000。
#include<iostream>
using namespace std;
unsigned long long dp[105][1005][2];
#define LIMIT_ULL 100000000000000000
int main(){
    int n,k;
    cin>>n>>k;
    dp[0][0][1]=1;//低位
    for(int i=1;i<=k;i++){
        for(int j=0;j<=n;j++){
            for(int k=0;k*i<=j;k++){
                dp[i][j][1]+=dp[i-1][j-k*i][1];
                dp[i][j][0]+=dp[i-1][j-k*i][0];
                dp[i][j][0]+=dp[i][j][1]/LIMIT_ULL;//低位的进位加到高位
                dp[i][j][1]=dp[i][j][1]%LIMIT_ULL;//低位去除进位
            }
        }
    }
    if(dp[k][n][0]){
        cout<<dp[k][n][0];
    }
    cout<<dp[k][n][1];
    return 0;
} 

以上比你不是最优的,可能会TLE

dp[i][j]+=dp[i-1][j-i*k]可以优化成dp[i][j]=dp[i-1][j]+dp[i-1][j-k]

因为当k>1时的计算结果,已经保存在了dp[i-1][j-k]

#include<iostream>
using namespace std;
unsigned long long dp[105][1005][2];
#define LIMIT_ULL 100000000000000000
int main(){
    int n,k;
    cin>>n>>k;
    dp[0][0][1]=1;
    for(int i=1;i<=k;i++){
        for(int j=0;j<=n;j++){
            if(j<i){
                dp[i][j][1]=dp[i-1][j][1];
                dp[i][j][0]=dp[i-1][j][0];
            }
            else{
                dp[i][j][1]=dp[i-1][j][1]+dp[i][j-i][1];
                dp[i][j][0]=dp[i-1][j][0]+dp[i][j-i][0];
                dp[i][j][0]+=dp[i][j][1]/LIMIT_ULL;
                dp[i][j][1]=dp[i][j][1]%LIMIT_ULL;
            }
        }
    }
    if(dp[k][n][0]){
        cout<<dp[k][n][0];
    }
    cout<<dp[k][n][1];
    return 0;
} 

猜你喜欢

转载自www.cnblogs.com/albert67/p/10323190.html
今日推荐