递归实现指数型枚举
实现思路:
1~n这n个数字,每个数字都有输出与不输出两种情况,所以所有的输出共有(2^n)种。
递归需要存储排列的数据,可以考虑使用两种方式进行存储:
1.全局数组存储
所有递归数据使用一个全局数组存储,在递归调用后需要还原状态。
#include <iostream>
#include <vector>
using namespace std;
vector<int> result;
void dfs(int n,int index)
{
if(n == index)
{
for(int i = 0;i < result.size();i++)
{
cout << result[i] << " ";
}
cout << endl;
return ;
}
dfs(n,index + 1);
result.push_back(index + 1);
dfs(n,index + 1);
result.pop_back(); // 递归调用后复位原状态
}
int main()
{
int n;
cin >> n;
dfs(n,0);
return 0;
}
2.使用函数参数存储
使用位运算表示(当前位为1表示该位表示的数存在)
#include <iostream>
using namespace std;
void dfs(int n,int index,int status)
{
if(n == index)
{
for(int i = 0;i < n;i++)
{
if(status >> i & 1)
{
cout << i + 1 << " ";
}
}
cout << endl;
return ;
}
dfs(n,index + 1,status); // 下一个数不考虑取
dfs(n,index + 1,status | 1 << index); // 取下一个数
}
int main()
{
int n;
cin >> n;
dfs(n,0,0);
return 0;
}
3.使用状态压缩的非递归做法
状态压缩的特性:可以枚举所有选与不选的情况。
可以用state的二进制表示形式中每位上的0/1
体现每个数字的’不选/选’。
#include<iostream>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin>>n;
for(int state=0;state<(1<<n);state++)
{
for(int j=0;j<n;j++)
{
if(state>>j&1)
cout<<j+1<<" ";
}
cout<<endl;
}
return 0;
}
yxc的示范代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 16;
int n;
int st[N]; // 状态,记录每个位置当前的状态:0表示还没考虑,1表示选它,2表示不选它
void dfs(int u)
{
if (u > n)
{
for (int i = 1; i <= n; i ++ )
if (st[i] == 1)
printf("%d ", i);
printf("\n");
return;
}
st[u] = 2;
dfs(u + 1); // 第一个分支:不选
st[u] = 0; // 恢复现场
st[u] = 1;
dfs(u + 1); // 第二个分支:选
st[u] = 0;
}
int main()
{
cin >> n;
dfs(1);
return 0;
}