搜索与图论_递归枚举

Posted hot-machine

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搜索与图论_递归枚举相关的知识,希望对你有一定的参考价值。

指数型枚举: 无个数限制

  • 题目描述: 从 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;
}

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

以上是关于搜索与图论_递归枚举的主要内容,如果未能解决你的问题,请参考以下文章

[算法读书笔记C++,搜索与图论]dijkstra算法

[算法读书笔记C++,搜索与图论]dijkstra算法

codevs——1019 集合论与图论

codevs 1019 集合论与图论

集合论与图论 图论部分 笔记总结

再谈排序与图论算法