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;
    }
    

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

  • 相关阅读:
    java操作生成jar包 和写入jar包
    jboss配置jndi连接池
    windows 域的LDAP查询相关举例
    LDAP error Code 及解决方法
    HDU 6417
    CF1299D Around the World
    codechef Chef and The Colored Grid
    Educational Codeforces Round 82 (Rated for Div. 2)
    CF1237F Balanced Domino Placements
    CF1254E Send Tree to Charlie
  • 原文地址:https://www.cnblogs.com/Hot-machine/p/13197940.html
Copyright © 2011-2022 走看看