zoukankan      html  css  js  c++  java
  • HDU-3555-Bomb

    这题就是数位dp的一道题目,我们首先把一个264范围内的数,也就是1018范围之内的数,给分解开来。
    分解之后,我们深搜它,深搜函数的参数分别是,长度、是不是4、是不是上界(也就是是不是我们搜索的这个数是不是当前搜索位的最大值)。
    对于深搜函数,我们的搜索边界就是,如果此时就剩下一位待搜索,也就是我们搜到了digit[0]的位置,我们就返回一个1值,此时条件即为len==0。
    抑或我们搜索的过程中,这一位不是上界,而是小于上界的其他数,并且我们的dp数组更新过,里面不是零,我们就返回之前的值,也就是dp[len][is4]它的值。
    它的值代表什么意思呢?它的意思就是说,我们之前搜索到len=2的时候,这一位不是4,然后我们对于它的个位搜索得到一个10,因为如果十位不是4的话,那这十个数里面肯定不会有49,所以dp[2][0]也就等于了10。
    而当我们从其它的分支进来的时候,我们发下,此时len相同,并且这一位也不是4,我们不需要再进行搜索了,我们有之前存下的值。
    这也就相当于是记忆化搜索了,相当于是一个非常优秀的剪枝。
    对于相同的位数,如果是4,我们之前还没存下的话,我们就继续搜索,搜得不是上界之时的dp值,然后供其他的分支使用即可。
    这是从深搜的角度解释记忆化搜索的,下面放一个视频解释,是另一个角度的,讲的还挺不错的。
    https://www.bilibili.com/video/av27156563?from=search&seid=2518917738675420605

    #include <iostream>
    #include <cstring>
    using namespace std;
    int digit[20];
    long long dp[20][2];
    
    long long dfs(int len,bool is4,bool limit)
    {
        if (len==0)
            return 1;
        if (!limit&&dp[len][is4])
            return dp[len][is4];
        long long cnt = 0, up_bound = (limit ? digit[len] : 9); 
        for (int i = 0; i <= up_bound;i++) {
            if (is4&&i==9)
                continue;
            cnt += dfs(len - 1, i == 4, limit && i == up_bound);
        }
        if (!limit)
            dp[len][is4] = cnt;
        return cnt;
    }
    
    long long solve(long long num)
    {
        int k = 0;
        while (num) {
            digit[++k] = num % 10;
            num /= 10;
        }
        return dfs(k, false, true);
    }
    
    int main()
    {
        long long t, n;
        cin >> t;
        while (t--) {
            cin >> n;
            memset(dp, 0, sizeof(dp));
            cout << n + 1 - solve(n) << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    CSS切割
    一台电脑 多个 tomcat
    CGI
    电源关系
    Monkey Test 命令使用
    html ul
    java 反射
    RTMP
    动态库
    flash 大文件上传
  • 原文地址:https://www.cnblogs.com/xyqxyq/p/10366575.html
Copyright © 2011-2022 走看看