什么是深度优先搜索(DFS)?
深度优先搜索属于图算法的一种,是一个针对图和树的遍历算法,英文缩写为DFS即Depth First Search。
深度优先搜索是图论中的经典算法,利用深度优先搜索算法可以产生目标图的相应拓扑排序表,利用拓扑排序表可以方便的解决很多相关的图论问题,如最大路径问题等等。
其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
深度优先的基本原则:按照某种条件往前试探搜索,如果前进中遭到失败(正如老鼠遇到死胡同)则退回头另选通路继续搜索,直到找到满足条件的目标为止。
下面是关于深度优先搜索的图示:
算法描述:
可以看出,我们必须知道顶点是否已经被访问过。
所以在具体实现时,我们可以用一个全局数组visited来记录顶点是否被访问过。
如果visited[i]的值为True,则顶点vi已经被访问过,否则没有被访问。
DFS背后的想法是尽可能深入到图形中,并在没有任何未访问的相邻顶点的情况下回溯到顶点。
递归地描述/实现算法非常容易:我们在一个顶点开始搜索。
在访问顶点之后,我们进一步对我们之前没有访问过的每个相邻顶点执行DFS。
这样我们就可以访问从起始顶点可到达的所有顶点。
算法实现:
int n;
vector<bool> visited;
void dfs(int v)
{
visited[v] = true;
for ()
{
if (!visited[u])
dfs(u);
}
}
DFS的运用:
走迷宫:
给一个n行m列的2维的迷宫,'S'表示迷宫的起点,'T'表示迷宫的终点,'#'表示不能通过的点,'.' 表示可以通过的点。 你需要从'S'出发走到'T',每次只能上下左右走动,并且只能进入能通过的点,每个点只能通过一次。现在要求你求出有多少种通过迷宫的的方案。
输入格式
第一行输入n,m(1≤n,m≤10)表示迷宫大小。接下来输入n 行字符串表示迷宫。
输出格式
输出通过迷宫的方法数。
样例输入
2 3
S.#
..T
样例输出
2
代码实现
1 #include <iostream>
2 #include<cmath>
3 #include<cstdlib>
4 #include<cstring>
5 #include<string>
6 #include <algorithm>
7 using namespace std;
8 typedef long long ll;
9
10 //调用Enter函数和DFS函数
11 void Enter();
12 void DFS(int i,int j);
13 int n,m,x,y,way;//n,m记录迷宫大小,x,y记录'S'的地址, way记录路径的数量
14 char Maze[10][10];//存储迷宫
15 int Flag[10][10];//在DFS函数中标记 0为没经过,1为已经经过
16
17
18 int main()
19 {
20 int i,j;
21 cin>>n>>m;
22 for(i=0;i<n;i++)
23 {
24 for(j=0;j<m;j++)
25 {
26 cin>>Maze[i][j];
27 }
28 }
29 Enter();//查找入口'S'位置,记录其坐标x,y位置
30 DFS(x,y);//用深度优先搜索函数统计其路径
31 cout<<way<<endl;
32
33 return 0;
34 }
35
36 void Enter()
37 {
38 for(int i=0;i<n;i++)
39 {
40 for(int j=0;j<m;j++)
41 {
42 if(Maze[i][j]='S')
43 {
44 x=i;
45 y=j;
46 return;
47 }
48 }
49 }
50 }
51
52 void DFS(int i,int j)
53 {
54 if(i<0||j<0||i>=n||j>=m)
55 {
56 return;
57 }
58 if(Maze[i][j]=='T')
59 {
60 way++;
61 return;
62 }
63 else if(Maze[i][j]=='#')
64 {
65 return;
66 }
67 else
68 {
69 if((Maze[i][j]=='.'||Maze[i][j]=='S')&&Flag[i][j]==0)
70 {
71 Flag[i][j]=1;
72 //迭代的过程
73 DFS(i,j+1);//向上遍历
74 DFS(i+1,j);//向右遍历
75 DFS(i,j-1);//向下遍历
76 DFS(i-1,+j);//向左遍历
77
78 Flag[i][j]=0;
79 }
80 }
81 }
View Code