关闭

POJ 3181 Dollar Dayz

100人阅读 评论(0) 收藏 举报
分类:

这里写图片描述

题意:输入n、k,问将n用1~k这k个数字进行拆分,有多少种拆分方法。例如:n=5,k=3则有以下5种拆分方法:
n=3+2
n=3+1+1
n=2+1+1+1
n=2+2+1
n=1+1+1+1+1

此题是个背包问题,如果想不到可以将其看作是一个普通动态规划。

dp[i][j] 表示用i种价格配出金额j的方案数。
状态转移方程:dp[i][j]=dp[i-1][j]+dp[i-1][j-i]+dp[i-1][j-2i]+dp[i-1][j-3j]…+dp[i-1][0]

状态转移方程就是将所有由i-1状态,通过添加k(=0,1,2…)个i可以到达dp[i][j]的状态的数字相加。如:dp[i-1][j]表示由i-1价格不需要添加i就可以到达金额j,dp[i-1][j-i]表示由i-1种价格需要再利用加个i且要添加1个价格i才能到达金额j,dp[i-1][j-2i]表示由i-1种价格需要再利用价格i且要添加2个i才能到达金额j,以此类推。

由于相加后得到的结果可能相当大,已经超过了long long,所以应该用大数。用两个unsigned long long 分别表示低位和高位,由于 unsigned long long 最大范围到 2^64-1 即:18446744073709551615 ;所以取一个比这个值小一个数量级同时又能被10整除的数作为limit。

#include <iostream>
using namespace std;

unsigned long long b[105][1005], a[105][1005];
unsigned long long inf = 1;

int main()
{

    int n, k;
    cin >> n >> k;
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    for (int i = 0; i < 18; ++i) {
        inf *= 10;
    }
    a[0][0] = 1;
    //dp[i][j] = dp[i – 1][j] + dp[i – 1][j – i] + dp[i – 1][j – 2 * i] + … + dp[i – 1][0]
    for (int i = 1; i <= k; ++i)
    {
        for (int j = 0; j <= n; ++j)
        {
            for (int m = 0; m*i <= j; ++m)
            {
                b[i][j] = b[i][j] + b[i - 1][j - m*i] + (a[i][j] + a[i - 1][j - m*i]) / inf;
                a[i][j] = (a[i][j] + a[i - 1][j - m*i]) % inf;
            }
        }
    }

    if (b[k][n]) {
        cout << b[k][n];
    }
    cout << a[k][n] << endl;

    return 0;
}

提交之后是可以过的,结果如下:
这里写图片描述


看了大神的分析后,觉得自己的A题之路还有如此的遥远。

这里写图片描述

仔细考虑可以发现其实可以转到dp[i][j]的状态有两种:一种是dp[i-1][j]就是不用i这个数字拼接j这个数字的方法数,另一种是a[i][j-i]就是用了i这个数字拼接得到j-i的方法数。那么状态转移方程可以写为dp[i][j]=dp[i-1][j]+a[i][j-i]。

#include<iostream>

using namespace std;

long long a[105][1005], b[105][1005];

int main() {
    int n, k;
    cin >> n >> k;
    long long inf = 1;
    for (int i = 0; i < 18; ++i) {
        inf *= 10;
    }
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    for (int i = 0; i <= k; ++i) {
        a[i][0] = 1;
    }
    //dp[i][j]=dp[i-1][j]+dp[i][j-i];
    for (int i = 1; i <= k; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (i > j) {
                b[i][j] = b[i - 1][j];
                a[i][j] = a[i - 1][j];
                continue;
            }
            a[i][j] = (a[i - 1][j] + a[i][j - i]) % inf;
            b[i][j] = b[i - 1][j] + b[i][j - i] + (a[i - 1][j] + a[i][j - i]) / inf;
        }
    }
    if (b[k][n]) {
        cout << b[k][n];
    }
    cout << a[k][n] << endl;
    return 0;
}

这里写图片描述

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

poj 3181 Dollar Dayz 题解(动态规划)

点击打开链接 Dollar Dayz Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:...
  • madaidao
  • madaidao
  • 2014-06-28 18:59
  • 304

POJ 3181 - Dollar Dayz(完全背包+高精度)

Description Farmer John goes to Dollar Days at The Cow Store and discovers an unlimited number of t...
  • u013534690
  • u013534690
  • 2014-09-04 21:31
  • 475

POJ 3181 Dollar Dayz 动态规划法题解

本题也是一种背包问题,就是需要求出有多少种组合。 本题的新意就是: 1 利用两个long long数表示大数的高位和低位就能满足不溢出了 2 高位和低位需要仔细计算好 建模: dp[i][j]:表示...
  • kenden23
  • kenden23
  • 2014-12-03 12:05
  • 1138

Poj 3181 Dollar Dayz【整数划分+大数】

Dollar Dayz Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5679   Accepted: 2130...
  • liuke19950717
  • liuke19950717
  • 2016-03-30 20:53
  • 600

poj 3181 Dollar Dayz (完全背包+高精度)

题意:求将n分解为大于等于1小于等于k的数,有多少种分法。(划分数问题) 分析: 1、可以用完全背包解。 for(i=1...k)       for(j=i...n)             dp[...
  • u012841845
  • u012841845
  • 2014-02-09 11:06
  • 860

poj 3181 Dollar Dayz (整数划分问题---递归+DP)

题目:http://poj.org/problem?id=3181 思路:将整数N划分为一系列正整数之和,最大不超过K。称为整数N的K划分。 递归:直接看代码: 动态规划:dp[i][j]:=将...
  • xiaozhuaixifu
  • xiaozhuaixifu
  • 2013-09-03 22:29
  • 1316

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

POJ 3181 Dollar Dayz(完全背包+简单高精度加法) http://poj.org/problem?id=3181 题意:        给你K种硬币,每种硬币分别是1美元,2美...
  • u013480600
  • u013480600
  • 2014-10-26 15:21
  • 1050

POJ 题目3181 Dollar Dayz(完全背包,技巧)

Dollar Dayz Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4231   Accepted: 1646...
  • yu_ch_sh
  • yu_ch_sh
  • 2014-12-07 16:51
  • 321

POJ 3181 Dollar Dayz【递推 拆分存大数】

Dollar Dayz Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5736   Ac...
  • wyjwyl
  • wyjwyl
  • 2016-04-13 21:42
  • 174

POJ 3181 Dollar Dayz(划分数详解+高精度)

划分数详解,多种划分数。   1. 将n划分成若干正整数之和的划分数。   2. 将n划分成k个正整数之和的划分数。   3. 将n划分成最大数不超过k的划分数。   4. 将n划分成若干奇正整数之和...
  • shao824714565
  • shao824714565
  • 2017-04-10 22:03
  • 254
    个人资料
    • 访问:46690次
    • 积分:847
    • 等级:
    • 排名:千里之外
    • 原创:28篇
    • 转载:75篇
    • 译文:0篇
    • 评论:3条
    文章分类
    最新评论