前言
看了许多的关于dfs的博客,自己也研究了好多遍,最终算是入门了,下面就简单的个人理解的原理以及结合一个简单的全排列实例进行讲解。
原理简介
DFS基于递归思想,递归思想就是把一个事拆分成若干见相同的小事共同组合完成,具体见下图的斐波那契的图文解决
这就是一个最典型的递归,入口f(5)出口就是每次递归的return;
说完递归就是dfs,其有两个重要的标志,也就是两个数组,一个用来标记该点是否被访问过,一个用来把该点放入数组,所以这两个标记是相辅相成的,一定同时出现;dfs就是随机选定一个起点将其标记为已经访问过的点,然后就是递归调用进行与其相邻的点的搜索,直到所有的点都被访问完。
话不多说上例子
全排列,也就是1-n,输出其所有的排列结果。
代码如下,接下来会详细解读代码:
#include <stdio.h>
#include <iostream>
using namespace std;
int a[101],b[101],n;
void print()
{
int i;
for(i=1;i<=n;i++)
{
cout<<a[i]<<' ';
}
cout<<endl;
}
inline void dfs(int i)
{
int j;
if(i==n+1)
{
print();
return;
}
for(j=1;j<=n;j++)
{
if(b[j]==0)
{
a[i]=j;
b[j]=1;
dfs(i+1);
b[j]=0;
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n;
dfs(1);
return 0;
}
注:以上代码来自csdn博客 Apro1066。
这个代码看上去不多,但是确实经典,有好多值得推敲的东西。
首先主函数中的dfs(1)
这是dfs函数进入,传入参数1就是从1开始,主要在dfs函数的理解,下面的图片展示了展示了这个过程。
下面是一个DFS的经典问题-走迷宫,大家可以结合代码做进一步的理解。
Code
#include<bits/stdc++.h>
using namespace std;
bool a[101][101]={0};
char b[101][101]; //存放迷宫
int flag=0; //如果能走出去就标记为1,反之为0
int xx[4]={0-1,0,1},yy[4]={-1,0,1,0};
int n,kx,ky; //n是迷宫的边长,kx是x进行加减之后的值,同理ky。
void dfs(int x,int y){
for(int i=0;i<=3;i++){
kx=x+xx[i];
ky=y+yy[i];
if((b[kx][ky] == '.'||b[kx][ky] == 'e')&&kx>=0&&ky>=0&&kx<n&&ky<n&&a[kx][ky]==0){
a[kx][ky]=1;
if(b[kx][ky] == 'e'){
flag = 1;
}else{
dfs(kx,ky);
}
}
}
}
int main(){
int k=1,sum;
cin>>sum;
while(k<=sum){
memset(a,0,sizeof(a)); //将标记数组a全部记为 0,表示这个点未走过
cin>>n;
for(int i = 0;i<n;i++){
for(int j=0;j<n;j++)
cin>>b[i][j];
}
for(int i = 0;i<n;i++){
for(int j=0;j<n;j++){
if(b[i][j]=='s')
dfs(i,j);
}
}
if(flag==1){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
k++;
}
return 0;
}
有不懂的地方或者有错误的地方欢迎评论批评指正。