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;    
    }
  • 相关阅读:
    523 vue组件化高级 插槽slot:slot基本使用,具名插槽,编译作用域,作用域插槽
    522 vue父子组件的访问方式: $children、$refs、$parent
    521 vue子组件向父组件传递数据
    520 vue父组件向子组件传递:props基本用法,props数据验证,props中的驼峰标识
    在 React 组件中使用 Refs 指南
    Flutter 代码开发规范
    Angular ZoneJS 原理
    vue中$refs, $emit, $on, $once, $off的使用
    详解Js加法运算符
    JavaScript 异常
  • 原文地址:https://www.cnblogs.com/Lyush/p/2635646.html
Copyright © 2011-2022 走看看