dfs的枚举共有三种分别是递归实现指数型枚举,递归实现排列型枚举,递归实现组合型枚举
递归实现指数型枚举的特点是选或者不选
排列型枚举特点是记录数值是否使用
组合型枚举的特点是有一个开始的循环的start
在函数体中要将根节点之后的节点枚举过来,在枚举的过程中进行递归
注意:递归中的return是不能忘记的;
递归实现指数型枚举:
#include<iostream>
using namespace std;
const int N=20;
int s[N];//记录状态的一个数组
int n;
void dfs(int u)//u代表的是递归到第几位了
{
if(u>n)
{
for(int i=1;i<=n;i++)
{
if(s[i]==1)
printf("%d ",i);
}
puts("");
return;
}
s[u]=1;
dfs(u+1);
s[u]=0;
s[u]=2;
dfs(u+1);
s[u]=0;
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
递归实现排列行的枚举
#include<iostream>
using namespace std;
const int N=12;
int n;
int s[N];//记录存入的数字
bool sr[N];//记录有没有被用过
void dfs(int u)
{
if(u>n)
{
for(int i=1;i<=n;i++)
{
printf("%d ",s[i]);
}
puts("");
return ;
}
for(int i=1;i<=n;i++)
{
if(!sr[i])
{
s[u]=i;
sr[i]=true;
dfs(u+1);
s[u]=0;
sr[i]=false;
}
}
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
递归实现数组的组合型枚举
#include<iostream>
using namespace std;
const int N=30;
int way[N];
int n,m;
void dfs(int u,int statr)
{
if(u>m)
{
for(int i=1;i<=m;i++)
{
printf("%d ",way[i]);
}
puts("");
return ;
}
for(int i=statr;i<=n;i++)
{
way[u]=i;
dfs(u+1,i+1);//这里要注意不能用statr+1来递归
way[u]=0;
}
}
int main()
{
cin>>n>>m;
dfs(1,1);
return 0;
}
思考:
是什么造成三个程序要这样写的
三个程序从根本上说是递归传入的参数不同,来实现不同的功能的