• 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;    
    }
  • 相关阅读:
    cd /d %~dp0是什么意思啊?
    [转]修改SDI主窗口Title
    版本控制
    (原创)日志处理(修改)
    (转)VC中让CListBox带有复选框
    (转)专业的程序员需要具备的思考能力:写一个程序需要注意多少细节问题
    vue中vcharts的使用
    1. 持续集成 简单介绍
    os.urandom函数用来获取一个指定长度的随机bytes对象
    python 列表中嵌套列表或列表推导式 如果合并成一个list
  • 原文地址:https://www.cnblogs.com/Lyush/p/2635646.html
Copyright © 2020-2023  润新知