dfs递归实现数字排列枚举
一:递归实现指数型枚举
从 1∼n这 n 个整数中随机选取任意多个,输出所有可能的选择方案。
输入样例:
3
输出样例:
3
2
2 3
1
1 3
1 2
1 2 3
思路
对于每个数字,都有两种可能:选取/不选取,因此对于n个数字,有2^n中组合可能
n表示枚举对象是1~n
递归边界是x==n+1,或者x>n,当已经递归到第n+1曾的时候,说明到达递归边界,此时输出
st数组是一个bool数组,st[i]==0表示不选该数,st[i]==1表示选该数
#include <iostream>
using namespace std;
const int N=20;
bool st[N]={0};//初始:false
int n;
void dfs(int x)
{
if(x>n)
{
for(int i=1;i<=n;i++)
if(st[i]==1)
cout<<i<<' ';
cout<<endl;
return ;
}
st[x]=1;
dfs(x+1);
//st[x]=0;
st[x]=0;
dfs(x+1);
// st[x]=0;
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
二、递归实现排列型枚举
把 $1∼n $这 n 个整数排成一行后随机打乱顺序,输出所有可能的次序。
数据范围
1 ≤ n ≤ 9 1≤n≤9 1≤n≤9
输入样例:
3
输出样例:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
思路
递归边界:同上
核心语句:
for(int i=1;i<=n;i++)
{
if(!st[i])
{
st[i]=1;
q[u]=i;
dfs(u+1);
//q[u]=0;
st[i]=0;
}
}
本题需要两个数组,st数组和q数组
st数组表示是否选过某个数字,如果选过则置为1,否则置为0
q数组的q[1-n]存储数字的排列顺序
#include <iostream>
using namespace std;
const int N=10;
int q[N],st[N];
int n;
void dfs(int u)
{
if(u==n+1)
{
for(int i=1;i<=n;i++) cout<<q[i]<<' ';
cout<<'\n';
return ;
}
for(int i=1;i<=n;i++)
{
if(!st[i])
{
st[i]=1;
q[u]=i;
dfs(u+1);
//q[u]=0;
st[i]=0;
}
}
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
三、递归实现组合型枚举
从 1 ∼ n 1∼n 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。
数据范围
n
>
0
n>0
n>0
0
≤
m
≤
n
0≤m≤n
0≤m≤n
n
+
(
n
−
m
)
≤
25
n+(n−m)≤25
n+(n−m)≤25
输入样例:
5 3
输出样例:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
思路
dfs(u,start)第一个参数u表示递归到第几层,第二个参数表示从哪个数字开始
u==m+1时,达到递归边界,结束并输出
start用来控制ways数字保存的下一个数字大于前一个数字
#include <iostream>
using namespace std;
const int N=30;
int ways[N];
int n,m;
void dfs(int u,int start)
{
if(u==m+1)
{
for(int i=1;i<=m;i++) cout<<ways[i]<<' ';
puts("");
return ;
}
for(int i=start;i<=n;i++)
{
ways[u]=i;
dfs(u+1,i+1);
}
}
int main()
{
cin>>n>>m;
dfs(1,1);
return 0;
}