AcWing 92. 递归实现指数型枚举 题解

AcWing 92. 递归实现指数型枚举

原题链接:AcWing 92. 递归实现指数型枚举 .

题目描述

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

输入格式
输入一个整数n。

输出格式
每行输出一种方案。

同一行内的数必须升序排列,相邻两个数用恰好1个空格隔开。

对于没有选任何数的方案,输出空行。

本题有自定义校验器(SPJ),各行(不同方案)之间的顺序任意。

数据范围
1≤n≤15
输入样例:

3

输出样例:


3
2
2 3
1
1 3
1 2
1 2 3

题目分析

本题的指数型枚举就是相当于枚举整个集合{1, 2, …, n}的所有子集
递归求指数型枚举就是回溯法的应用

区间[1, n]中的每个数都有两种选择:选择此数和不选择此数
所有递归过程为:
①选择此数,递归求解,恢复现场
②不选此数,递归求解,恢复现场

递归终点:1–n中所有数都枚举过即枚举数cur>n,直接终止

c++代码实现

#include <iostream>
#include <cstdio>
using namespace std;

const int N = 20;
bool st[N];//表示数是否被选择过

void dfs(int cur, int n) {
    if(cur > n) {
        for(int i = 1; i < cur; ++i) {
            if(st[i]) printf("%d ", i);
        }
        puts("");
        return ;
    }
    //枚举第cur个数
    st[cur] = true;//选择数cur
    dfs(cur+1, n);
    st[cur] = false;//不选数cur,并恢复现场
    dfs(cur+1, n);
}

int main() {
    int n;
    scanf("%d", &n);
    dfs(1, n);
    return 0;
}

非递归算法

一个大小为集合的所有子集数为2n
对应了0—2n所有数的的二进制表示,每个数的二进制表示看成一个子集

#include <iostream>
#include <cstdio>
using namespace std;

int main() {
    int n;
    cin>>n;
    for(int i = 1; i <= 1<<n; ++i) {
        for(int j = 0; j < n; j ++) {
            if(i>>j & 1){
                printf("%d ", j+1);
            }
        }
        puts("");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/mwl000000/article/details/108188485