zoukankan      html  css  js  c++  java
  • 搜索_递归枚举

    指数型枚举: 无个数限制

    • 题目描述: 从 1~n 这 n 个整数中随机选取任意多个,输出所有可能的选择方案。

    朴素dfs枚举

    int n;
    vector<int> ans;
    void calc(int x) {
        if(x == n + 1) {
            for(auto c: ans) printf("%d ", c);
            puts("");
            return ;
        }
        calc(x + 1);
        
        ans.push_back(x);
        calc(x + 1);
        ans.pop_back(); // 恢复原始状况
        
    }
    
    void solve() {
        scanf("%d", &n);
        calc(1);
    }
    

    二进制压缩版dfs

    int n;
    void dfs(int u, int state) { // state 的二进制表示中,选过的数所对应的二进制位为1
        if(u == n) { // 从零开始到n - 1结束
            for(int i = 0; i < n; i++) {
                if(state >> i & 1) printf("%d ", i + 1); // state的二进制表示中为一的表示选中,输出
            }
            printf("
    ");
            return ;
        }
        dfs(u + 1, state); // 不选
        
        dfs(u + 1, state | 1 << u);  // 选, 并将其置为一
    
    }
    
    void solve() {
        scanf("%d", &n);
        dfs(0, 0);
    }
    

    组合型枚举:有个数限制

    • 题目描述: 从 1~n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。

    朴素dfs: 运行时间过长

    vector<int> ch;
    int a, b;
    void calc(int x) {
        if(x > a + 1) return ;
        if(ch.size() == b) {
            for(int i = 0; i < ch.size(); i++) printf("%d ", ch[i]);
            printf("
    ");
            return ;
        }
        ch.push_back(x);
        calc(x + 1);
        ch.pop_back();
        
        calc(x + 1);
    } 
    
    void solve() {
        scanf("%d%d", &a, &b);
        calc(1);
        return 0;
    }
    

    二进制压缩版dfs

    int a, b;
    void dfs(int u, int state, int s) { 
        if(s + a - u < b) return ; // 当前加上剩下的所有的也不满足条件
        if(s == b) {
            for(int i = 0; i < a; i++) {
                if(state >> i & 1) printf("%d ", i + 1);
            }
            printf("
    ");
            return;
        }
        dfs(u + 1, state | 1 << u, s + 1); // 选
        dfs(u + 1, state, s);  // 不选
    }
    
    void solve() {
        scanf("%d%d", &a, &b);
        dfs(0, 0, 0);
    }
    

    排列型枚举 :排列数

    • 题目描述:把 1~n 这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。

    朴素版

    • 建立一个布尔数组判断数是否被选过
    const int N = 10;
    vector<int> ch;
    bool st[N];
    int n;
    
    void dfs(int u) {
        if(u == n + 1) {
            for(int i = 0; i < n; i++) printf("%d ", ch[i]);
            printf("
    ");
            return ;
        }
        for(int i = 1; i <= n; i++) {
            if(!st[i]) {
                ch.push_back(i);
                st[i] = true;
                dfs(u + 1);
                st[i] = false; // 恢复现场
                ch.pop_back(); // 恢复现场
            }
        }
    }
    
    void solve() {
        scanf("%d", &n);
        dfs(1);
        return 0;
    }
    

    二进制压缩版dfs

    • 使用一个32位整型变量,使用其二进制表示数是否被使用, 为1的位表示已经使用
    const int N = 10;
    vector<int> ch;
    int n;
    
    void dfs(int u, int state) {
        if(ch.size() == n) {
            for(int i = 0; i < n; i++) printf("%d ", ch[i]);
            printf("
    ");
            return ;
        }
        for(int i = 1; i <= n; i++) {
            if(!((state >> i) & 1)) {
                ch.push_back(i);
                dfs(u + 1, state | 1 << i); // 选择该数,置为1
                ch.pop_back(); // 恢复现场
            }
        }
    }
    
    void solve() {
        scanf("%d", &n);
        dfs(1, 1);
        return 0;
    }
    

    将递归程序转换成非递归程序

  • 相关阅读:
    循环队列
    快速排序
    单链表
    数学之美总结
    我要的生活...
    北京,我来了
    冷暖自知 by 张楚
    瞎掰,关于网站的推广和如何摧毁贴吧<上>
    Adobe 拟发布WEB PS
    Web阅读摘录[持续更新]
  • 原文地址:https://www.cnblogs.com/Hot-machine/p/13197940.html
Copyright © 2011-2022 走看看