DFS

一.深度优先搜索(dfs)

1.什么叫dfs

深度优先搜索类似于树的先序遍历;

是利用栈或者递归的方式实现的,体现出了后进先出的特点;

通俗来说就是一次访问一条路,一直朝着一个方向探索,直到遇到死路退回到前一个分支,继续探索;

一般来说,深度搜索解决的问题主要为寻求所有解和连通性。

2.遍历过程

(1)从图中某个初始顶点v出发,首先访问初始顶点v。

(2)然后依次从v的未被访问的邻接点w,再从w出发进行深度优先遍历,直到图中所有与v有路径相通的的顶点都被访问过为止。

3.算法设计

解决问题:
(1)如何确定一个顶点是否访问过?

设置一个visited[]全局数组,

visited[i]=0表示顶点i没有访问;

visited[i]=1表示顶点i已经访问过。

(在图中也可以修改图本身来实现)

4.dfs算法模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void dfs(int s)
{
if(找到解了)
{
相应的操作;
return
}
尝试每一种可能
{
if(满足条件)
{
标记走过;
进行下一步dfs;
回溯一步; //恢复原状态
}
}
}

代码

  1. 最短路径(迷宫问题)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
	//用dfs来计算最短路径
#include<stdio.h>
int r,c,num=10000;
char map[41][41];
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
void dfs(int x,int y,int k)
{
if(x==r&&y==c)
{
if(num>k)
{
num=k;
}
}
for(int i=0;i<4;i++)
{
int nx=x+dx[i];
int ny=y+dy[i];
if(nx>=1&&nx<=c&&ny>=1&&ny<=r&&map[ny][nx]=='.')
{
map[ny][nx]='#';
dfs(nx,ny,k+1);
map[ny][nx]='.';
}
}
}
int main()
{
scanf("%d%d",&r,&c);
for(int i=1;i<=r;i++)
{
for(int j=1;j<=c;j++)
{
scanf(" %c",&map[i][j]);
}
}
map[1][1]='#';
dfs(1,1,1);
printf("%d",num);
}

2. 路径判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
//dfs遍历是否能够从(ha,la)到(hb,lb)
#include<stdio.h>
#include<string.h>
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
int n,ha,la,hb,lb,nx,ny;
bool flag;
char map[200][200];
void dfs(int x,int y)
{
for(int i=0;i<4;i++)
{
nx=x+dx[i];
ny=y+dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<n&&map[nx][ny]=='.')
{
map[nx][ny]='#';
if(nx==hb&&ny==lb)
{
printf("YES\n");
flag=true;
break;
}
else
dfs(nx,ny);
}
}
}
int main()
{
int k;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
flag=false;
scanf("%d",&n);
memset(map,'#',sizeof(map));
for(int j=0;j<n;j++)
for(int h=0;h<n;h++)
{
scanf(" %c",&map[j][h]);
}
scanf("%d%d%d%d",&ha,&la,&hb,&lb);
if(map[ha][la]=='#'||map[hb][lb]=='#')
{
printf("NO\n");
continue;
}
else
{
map[ha][la]='#';
//标记起点走过
dfs(ha,la);
}
if(!flag)
printf("NO\n");
}
return 0;
}