zoukankan      html  css  js  c++  java
  • POJ 3181 Dollar Dayz 简单DP

    这DP虽然简单

    但是思考一下还是挺好的

    题意是

    1,2,3,4....k 用加法凑成N

    每个数可取不限个数


    令dp[i][j] 表示前i种数凑成j的方案数

    然后dp[i][j] = dp[i - 1][j] + dp[i - 1][j - i] + dp[i - 1][j - 2 * i]........dp[i - 1][j - k * i]

    这样子

    然后代码如下,由于结果要爆long long ,所以用两个long long 数存高位和低位

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define MAXN 111111
    #define INF 1000000007
    using namespace std;
    pair<long long, long long> dp[111][1111];
    long long mod = 10000000000000000LL;
    int n, m;
    int main()
    {
        scanf("%d%d", &n, &m);
        dp[0][0].second = 1;
        dp[0][0].first = 0;
        for(int i = 1; i <= m; i++)
        {
            for(int j = 0; j <= n; j++)
                for(int k = j; k >= 0; k -= i)
                {
                    dp[i][j].first += dp[i - 1][k].first;
                    dp[i][j].second += dp[i - 1][k].second;
                    if(dp[i][j].second >= mod)
                    {
                        dp[i][j].first += dp[i][j].second / mod;
                        dp[i][j].second %= mod;
                    }
                }
        }
        if(dp[m][n].first > 0)
            printf("%I64d%I64d
    ", dp[m][n].first, dp[m][n].second);
        else printf("%I64d
    ", dp[m][n].second);
        return 0;
    }


    然后就是优化一下

    dp[i][j] = dp[i - 1][j] + dp[i - 1][j - i] + dp[i - 1][j - 2 * i]........dp[i - 1][j - k * i]

    其实可以发现

    dp[i][j - k * i] 与dp[i][j - (k - 1)i] 之间是可以转移的

    无非是多用了一个i而已

    那么优化成了dp[i][j] = dp[i - 1][j] + dp[i][j - i]

    dp[i - 1][j] 代表的是前i-1种数凑成j的方案数

    dp[i][j - i]代表的是是用了前i种数凑成j - i的方案数

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define MAXN 111111
    #define INF 1000000007
    using namespace std;
    pair<long long, long long> dp[111][1111];
    long long mod = 10000000000000000LL;
    int n, m;
    int main()
    {
        scanf("%d%d", &n, &m);
        dp[0][0].second = 1;
        dp[0][0].first = 0;
        for(int i = 1; i <= m; i++)
        {
            for(int j = 0; j <= n; j++)
            {
                dp[i][j] = dp[i - 1][j];
                if(j - i < 0) continue;
                dp[i][j].first += dp[i][j - i].first ;
                dp[i][j].second += dp[i][j - i].second;
                if(dp[i][j].second >= mod)
                {
                    dp[i][j].first += dp[i][j].second / mod;
                    dp[i][j].second %= mod;
                }
            }
        }
        if(dp[m][n].first > 0)
            printf("%I64d%I64d
    ", dp[m][n].first, dp[m][n].second);
        else printf("%I64d
    ", dp[m][n].second);
        return 0;
    }


    然后还能优化的就是空间了

    观察转移方程

    dp[i][j] = dp[i - 1][j] + dp[i][j - i]

    发现只跟i和i-1有关系

    并且和i - 1有关系得时候跟j没关系

    也就是可以用一个一维的状态转移方程就行了

    dp[j] = dp[j] + dp[j - i]

    其中dp[i - 1][j]实际上在i - 1 循环后已经隐含的转移到了dp[i][j]中了

    也就是dp[j]

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #define MAXN 111111
    #define INF 1000000007
    using namespace std;
    pair<long long, long long> dp[1111];
    long long mod = 10000000000000000LL;
    int n, m;
    int main()
    {
        scanf("%d%d", &n, &m);
        dp[0].second = 1;
        dp[0].first = 0;
        for(int i = 1; i <= m; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(j - i < 0) continue;
                dp[j].first += dp[j - i].first ;
                dp[j].second += dp[j - i].second;
                if(dp[j].second >= mod)
                {
                    dp[j].first += dp[j].second / mod;
                    dp[j].second %= mod;
                }
            }
        }
        if(dp[n].first > 0)
            printf("%I64d%I64d
    ", dp[n].first, dp[n].second);
        else printf("%I64d
    ", dp[n].second);
        return 0;
    }


  • 相关阅读:
    cookie写入,读取,删除
    javascript模板
    javascript思维导图
    html+css
    Google Java编程风格指南
    mysql1449 The user specified as a definer ('root'@'%') does not exist 解决方法
    mongoDB非正常关闭后无法启动问题
    Android应用程序注册广播接收器(registerReceiver)的过程分析
    Android应用程序在新的进程中启动新的Activity的方法和过程分析
    Android系统中的广播(Broadcast)机制简要介绍和学习计划
  • 原文地址:https://www.cnblogs.com/riskyer/p/3290277.html
Copyright © 2011-2022 走看看