简介

深度优先搜索Depth First Search是对图论问题的分析解决,其核心思想就是就是解决1、当下应该如何做;2、下一步如何做与现在这一步如何做是一样的;3、边界条件的判断;

基本模型-通用套路

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void dfs(step)
{
/*1.判断边界,判断本阶段的DFS是否已经结束了*/
if(foo == bar){
/*Do something*/
return ;
}
/*2.尝试每一种可能,类似于走迷宫中的在每一个点尝试每个方向*/
for(i=0;i<_MAX_;++i)
{
do_something();
dfs(step+1);//进行下一步
undo_something();
}
return ;
}

走迷宫-应用深度优先搜索

思路:

  1. 确定深度探索的方向:迷宫为二维数组,每个点最多只有上下左右四个方向,因此使用一个4元素的二维数组来表示探索方向,同时对每个点增加迷宫越界判断/障碍物判断(迷宫内有障碍物)
  2. DFS的边界条件即为找到了终点(当前坐标等于终点坐标)

实现

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*2017-9-15 19:32:57
project:Depth First Search(DFS)
author:zhy
IDE:VSCode
Compile:gcc -v 4.8.1
*/

#include<stdio.h>
#include<stdlib.h>

#define _MAX_X 5
#define _MAX_Y 4

/*绘制迷宫的函数*/
int draw();

int arr[_MAX_X][_MAX_Y]={0}; //迷宫图
int endx=3,endy=2; //目的地
int startx=0,starty=0; //起点
int stop[][2]={{0,2},{2,2},{
3,1},{4,3}}; //障碍物
int num=1;
int min=-1;
int next_step[][2]={{0,1},{1,0},{0,-1},{-1,0}}; //上下左右四个方向的移动方向

void dfs(int x,int y,int step)
{
int nextx=0,nexty=0; //下一步的坐标
int i=0,j=0;
arr[0][0]=-1; //标记原点为障碍,防止深度搜索时回溯

if(x > _MAX_X || y > _MAX_Y || x < 0 || y < 0){
return ;
}

//DFS第一步,边界条件判断
if(x == endx && y == endy){ //进入if意味着DFS已经找到终点
if(step < min || min <= 0){
min = step;
}
//还原起点和终点的标记状态,以使它们能正确绘制
arr[0][0]=-3;
arr[endx][endy]=-2;
draw();
num=0;
return;
}

//DFS第二步,尝试所有可用的搜索办法
for(i=0;i < sizeof(next_step)/sizeof(int)/2;++i)
{
//计算下一步的坐标并且判断是否越出了迷宫的边界
nextx = x + next_step[i][0];
nexty = y + next_step[i][1];
if(nextx >= _MAX_X || nexty >= _MAX_Y || nextx < 0 || nexty < 0){
continue;
}

//判断该点是否已经在路径中(即是否已经走过了,不能再往回走)或是否为障碍物
if((arr[nextx][nexty] != -1) && (arr[nextx][nexty] <= 0)){
arr[nextx][nexty]=num++; //该点可走,走过该点并标记它为‘走过了’
dfs(nextx,nexty,step+1); //进入下一级深度继续搜索
arr[nextx][nexty]=0; //从上一行的dfs返回,将它还原为未走状态
}
}
return;
}

int main(int argc,char *argv[])
{
int i=0,j=0;
int step=0; //记录最短路径的步数

//为障碍物、起点终点等对应的数组元素赋值
for(i=0;i < sizeof(stop)/sizeof(int)/2;++i){
arr[stop[i][0]][stop[i][1]] = -1; //障碍物
}
arr[endx][endy]=-2; //目的地
arr[startx][starty]=-3; //出发点

draw();
dfs(startx,starty,step);

return 0;
}

int draw()
{
int i,j;

//打印迷宫图
putchar('\n');
for(i=0;i<_MAX_X;++i){
for(j=0;j<_MAX_Y;++j)
{
switch(arr[i][j]){
case 0:
printf("_");
break;
case -1:
printf("X");
break;
case -2:
printf("O");
break;
case -3:
printf("S");
break;
default:
printf("%d",arr[i][j]);
break;
}
printf("|");
}
printf("\n");
}
putchar('\n');
}

执行结果

pic_from_my_old_csdn