zoukankan      html  css  js  c++  java
  • HDU3555 Bomb 数位DP

    这题的状态真的是很难想到,网上的代码都惊人的相似...

    另一种解法,相比而言好接受一点:

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    using namespace std;
    typedef unsigned long long Int64;
    
    Int64 dp[20][3], N;
    
    int digit[20];
    
    Int64 dfs(int pos, int statu, int limit)
    {
        if (pos == -1) { // 如果到了已经枚举了最后一位,并且在枚举的过程中有49序列出现 
            return statu == 2;
        }
        if (!limit && dp[pos][statu] != -1) return dp[pos][statu];  // 对于有限制的询问我们是不能够记忆化的 
        Int64 sum = 0;
        int s, end = limit ? digit[pos] : 9; // 确定这一位的上限是多少 
        for (int i = 0; i <= end; ++i) { // 每一位有这么多的选择 
            s = statu; // 有点else s = statu 的意思 
            if (statu == 1 && i == 9) s = 2;
            if (statu == 0 && i == 4) s = 1;
            if (statu == 1 && i != 4 && i != 9) s = 0;
            sum += dfs(pos-1, s, limit && i == end);
        }
        if (!limit) dp[pos][statu] = sum;
        return sum;
    }
    
    Int64 Cal(Int64 x)
    {
        int len = -1;
        while (x != 0) {
            digit[++len] = x % 10;
            x /= 10;
        }
        return dfs(len, 0, 1);
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while (T--) {
            memset(dp, 0xff, sizeof (dp));
            scanf("%I64u", &N);
            printf("%I64u\n", Cal(N));
        }
        return 0;    
    }

    详见代码:

    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    typedef unsigned long long int Int64;
    
    Int64 N, dp[25][3];
    
    int digit[25];
    
    /*
    dp[len][0] 表示前len位没有49的数字的个数
    dp[len][1] 表示前len位没有49但是以9结尾的数的个数
    dp[len][2] 表示前len位有49的状态 
    */
    
    void pre()
    {
        dp[0][0] = 1;
        for (int i = 1; i <= 20; ++i) {
            dp[i][0] = 10 * dp[i-1][0] - dp[i-1][1];
            dp[i][1] = dp[i-1][0];
            dp[i][2] = 10 * dp[i-1][2] + dp[i-1][1];
        }
    }
    
    int main()
    {
        pre();
        int T, len, flag;
        Int64 ret;
        scanf("%d", &T);
        while (T--) {
            flag = ret = 0;
            scanf("%I64u", &N);
            ++N;
            memset(digit, 0, sizeof (digit));
            for (len = 1; N; ++len) {
                digit[len] = N % 10;
                N /= 10;
            }
            for (int i = len-1; i >= 1; --i) {
                ret += digit[i] * dp[i-1][2]; // 已经有49就直接加上 
                if (flag) {
                    ret += digit[i] * dp[i-1][0];
                }
                else if (!flag && digit[i] > 4) {
                    ret += dp[i-1][1];    
                }
                if (digit[i+1] == 4 && digit[i] == 9) {
                    flag = 1;
                }
            }
            printf("%I64u\n", ret);
        }
        return 0;    
    }
  • 相关阅读:
    打砖块代码解析
    C语言拾遗(一):整型提升
    高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(下) <转>
    c10k测试:每连接新线程回显服务器(echo server) (转)
    高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(上) <转>
    java基础总结equals与==
    Java的运行机制概括
    Java 基础总结反射的基本操作
    python爬取基础网页图片
    px,dp,sp以及像素密度
  • 原文地址:https://www.cnblogs.com/Lyush/p/2635646.html
Copyright © 2011-2022 走看看