题目
题目地址:acwing 92.递归实现指数型枚举
从 1∼n 这 n个整数中随机选取任意多个数,输出所有可能的选择方案。
分析 :
方法一:
题目很短 大致意思就是将所有可能的组合输出 比如:n=3 时
1 2 3
可输出的组合为{1}{2}{3}{1,2}{1,3}{1,2,3}{2,3}{空集}
这很容易就能想到数学上的子集问题 :
一个为 n 的数集 一共有多少子集
数学老师交过我们 一共有2^n个子集
那么是怎么找的呢?
那么在c语言中怎么写出来呢
有人可能说用数组 但是有10种就要有10个数组有n个就要用n个数组
与是就有了下面的方法:
方法二:
咱们拿n=3的情况下来进行讲解
第一步
先看以一个数 在这里就是1
分为选或者不选 选代表 1 不选代表 2 不确定的则用 0 来补充
第二步
在看第二位 是选还是不选 规则和上面的一样
第三步
再看第三位 是选还是不选 规则和上面一样
第四步
这就得到了 1 2 3 这个示例的一个答案 那么其他的呢 ?这就需要向上回溯 寻找另一种状态 比如当前答案是 123 那么就需要回溯到选择第三位的时候 再向下选就会得到 12 这个答案
那么回溯时 第三位的值就可以定为 0
那么 看代码!
#include<bits/stdc++.h>
using namespace std;
const int N=10010;//最好大一点用来作为数组的长度
int a[N];// 用a数组用来存放答案
int n;
void dfs(int x){
//当x>n时就可以停止地推 进行输出
if(x>n){
for(int i=1;i<=n;i++)
if(a[i]==1)
printf("%d ",i);//数组里的元素其实是用来存放选或者不选的----->(1/2) 下标才上指当前元素
printf("\n");
return ;
}
//选用1来表示 不选用0来表示
a[x]=2;//不选的时候
dfs(x+1);
a[x]=0;
a[x]=1;//选的时候
dfs(x+1);
a[x]=0;//代码进行回溯时 将上一层待选数 变为 0--->未选
}
int main(){
cin >> n;
dfs(1);
return 0;
}
运行结果:
3
2
2 3
1
1 3
1 2
1 2 3