DFS的应用–深度优先搜索
给出一个数n,要求1到n这n个数的所有全排列,首先最容易让人想到的方法就是用枚举的方式循环嵌套循环暴力将这n个数的所有全排列列举出来。可是这样的枚举方法倘若n这个数值小的情况下还可以,但若大的时候就很繁琐且运行效率不高。
例如酱紫:
for(i=1;i<=3;i++)
{
for(j=1;j<=3;j++)
{
if(j==i)
continue;
for(k=1;k<=3;k++)
{
if(k==i||k==j)
continue;
cout<<i<<" "<<j<<" "<<k<<endl;
}
}
}
比如n为3的时候,这样的for循环来依次枚举,可以看出,当n更大的时候,其中要嵌套的循环语句中要判断语句排除的将要更加多,更繁琐。
所以我们想到如何利用DFS使用。
深度优先搜索其实就是一个递归的过程,dfs与栈有关,bfs与队列有关。
此题n个数排列必然会产生n个位置,那么这每一个位置上都要放上一个1-n的数字吧。我们每一个位置上都可以先试探一下可以放哪个数(用一个for即可),当然试探过程中怎么样判断它是是否在前面的某个位置被用过了呢?这里我们可以用一个数组book来标记一下,例如初始化都为0,用过的就让此刻的位置book[step]为1。然后找到可以放下的数后,就可以dfs(step+1)去到下一个位置去寻找了。这个地方的问题被解决了,就是要考虑边界问题了,也就是说递归到什么地方去回溯,比如这里,n个位置都有数后即可完成一种排列,就可以让他回去寻找其他不同的排列顺序了。即这道题边界step==n+1的时候就可以返回了。
代码如下
#include <iostream>
using namespace std;
int a[1001],book[1001]={
0},n;
void dfs(int step)
{
int i;
if(step==n+1)
{
for(i=1;i<step;i++)
cout<<a[i]<<" ";
cout<<endl;
return;
}
for(i=1;i<=n;i++)
{
if(book[i]==0)
{
book[i]=1;
a[step]=i;
dfs(step+1);
book[i]=0;
}
}
return;
}
int main()
{
cin>>n;
dfs(1);
return 0;
}