• 数位dp入门学习之路(正常枚举“过渡到”dfs枚举)


    前言:数位dp就是换一种穷举方式。额......我第一次看这句话也懵,哎,资深学渣,来记个笔记先。

    正常枚举“过渡到”dfs枚举(这里暂时是穷举的数为:1、10、100、1000、10000....,要穷举任意数在后面给出)

    其实有些兄弟用了递推关系来做这类题,但个人感觉那种解题方式还是太花时间了。。。。。。。。。。

    正常枚举:

    #include <iostream>
    #include <cstdio>
    #define ll long long
    
    using namespace std;
    
    int main() {
        for (int i = 0; i <= 1000) {
            printf("%d
    ", i);
        }
        return 0;
    } 

    结果:略(看数学答案也是这样)

    dfs枚举:注意pos参数的意思是枚举到当前数字的位数。dfs是从数字的高位往低位枚举(当数字的枚举是也是从小到大的)。num用于记录当前枚举的数字

    dfs(pos=0, num); 表示只枚举长度为1的数字,最大数为9
    dfs(pos=1, num); 表示只枚举长度为2的数字,最大数为99
    dfs(pos=2, num); 表示只枚举长度为3的数字,最大数为999
    最好自己动手测一下其他结果,不要光靠脑袋想,除非...........哈哈
    #include <iostream>
    #include <cstdio>
    #include <vector>
    #define ll long long
    
    using namespace std;
    // dfs穷举 
    void dfs(int pos, vector<int> &num) {
        if (pos == -1) {
            // 打印数
            for (int i = 0; i < num.size(); i++)
                printf("%d", num[i]);
            printf("
    "); 
            return;
        }
        for (int i = 0; i <= 9; i++) {
            num.push_back(i);// 添加 
            dfs(pos-1, num);
            num.erase(num.end()-1);// 回溯一下 
        }
    }
    
    int main() {
        vector<int> num;
        dfs(2, num);
        return 0;
    } 

    结果显示如下(不完整):

    枚举到任意数:参数limit的引入(其他博主都是取的这个参数名)

    正常枚举到任意数:(不用多说)

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #define ll long long
    
    using namespace std;
    
    int main() {
        for (int i = 0; i <= 任意数; i++) {
            // ...... 
        }
        return 0;
    } 

    dfs任意数枚举:参数limit的用处,用来控制枚举上界位的数字,为Boolean值,为true的时候,表示当前枚举pos位上的数字有上界,相反则没有。

    比如:任意数 = 321,limit初始为true

    当枚举到百位上时,3就是百位上的上界,百位就只能取0、1、2、3,而当百位是3时,十位的枚举此时就有了上界2,同理,当百位为3,十位为2,则个位的上界为1。但是当枚举的百位小于3,也就是百位取值为0、1、2时,十位和个位的取值可以是0-9,此时不管怎么取值也不会超出最大值321,因为百位已经是0、1、2开头了,同样个位也是同样的道理。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #define ll long long
    
    using namespace std;
    
    int a[20];// 保存当前数字各个位上的数字 
    
    // dfs穷举 
    void dfs(int pos, bool limit, vector<int> &num) {
        if (pos == -1) {
            // 打印数
            for (int i = 0; i < num.size(); i++)
                printf("%d", num[i]);
            printf("
    "); 
            return;
        }
        // 这里的up用来控制最大上界(就是枚举的数不能超过n = 123) 
        int up = limit?a[pos]:9;
        for (int i = 0; i <= up; i++) {
            num.push_back(i);// 添加 
            // limit && i == a[pos] 为true时表示如果当前位有上界,并且枚举到了最大上界值
            dfs(pos-1,  limit && i == a[pos], num);
            num.erase(num.end()-1);// 回溯一下,删除刚才添加的数字 
        }
    }
    
    int main() {
        vector<int> num; 
        int n = 123;
        int pos = 0;
        // 分解数字 
        while(n > 0) {
            a[pos++] = n%10;
            n /= 10;
        }
        dfs(pos-1, true, num);
        return 0;
    } 

    结果如下:

    。。。。疫情过年好无聊

  • 相关阅读:
    ToString 格式化数值
    肾积水
    十月一日
    9月27日 星期六
    080929 气温骤降
    東京の空
    9月26日 星期五
    9月30日 星期二
    粉蓝房子&电影
    080922 雨
  • 原文地址:https://www.cnblogs.com/hello-dummy/p/12298947.html
Copyright © 2020-2023  润新知