# 简介

深度优先搜索算法(英语:Depth-First-Search,DFS)是一种用于遍历或搜索树或图的算法。这个算法会尽可能深地搜索树的分支。当节点 v 的所在边都己被探寻过,搜索将回溯到发现节点 v 的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。这种算法不会根据图的结构等信息调整执行策略。 —— 维基百科

​ 个人觉得深度优先搜索(DFS)是非常符合直觉的一种搜索算法。

​ 举一个简单的例子,假设 Alice 正在走迷宫,她只有一个人,因此她采取了这种策略:

​ 不断向前走,如果遇到岔路口,那么就随便选择一条路口进入,并把自己已经探索过的位置做上标记,一直保持这个方法,直到确认某条路是死路,或者找到迷宫的出口。如果这条路是死路,那么就往回退到上一个路口,看看有没有没探索过的分支。一直这样走遍整个迷宫,就能够找到出口。

# DFS 的递归实现

# 问题示例

​ 以一个问题为例:P1605 迷宫 - 洛谷

​ 这个问题的迷宫较小,可以通过 DFS 的递归实现来解决:

#include <iostream>
#include <vector>
using namespace std;
int counter = 0;
void mazePathfinding(vector<vector<int> > &maze, const int n, const int m, const int x, const int y, const int finishX, const int finishY)
{
    if ( (x < 0) || (y < 0) || (x >= n) || (y >= m))            // 数组越界 就相当于达到了迷宫的边缘
    {
        return;
    }
    if ( maze[x][y] == 1 )                                      // 撞墙
    {
        return;
    }
    if ( (x == finishX) && (y == finishY) )                     // 如果走到了终点 算一种解法 计数器 + 1
    {
        counter++;
        return;
    }
    // 如果既不会走不通 也没到终点 那么就需要尝试继续向前探索迷宫了
    maze[x][y] = 1;                                             // 先把目前的位置标记为已访问 这里直接标记为 1 也就是墙
    mazePathfinding(maze, n, m, x-1, y, finishX, finishY);      // 尝试向左走一步
    mazePathfinding(maze, n, m, x+1, y, finishX, finishY);      // 尝试向右走一步
    mazePathfinding(maze, n, m, x, y-1, finishX, finishY);      // 尝试向上走一步
    mazePathfinding(maze, n, m, x, y+1, finishX, finishY);      // 尝试向下走一步
    maze[x][y] = 0;                                             // 这一步把已访问的状态清除 以免影响到之后的搜索
}
int main()
{
    int N = 0, M = 0, T = 0;
    cin >> N >> M >> T;                                         // 输入参数
    vector<vector<int> > maze(N, vector<int>(M));               // 创建迷宫
    maze.assign(N, vector<int>(M, 0));                          // 默认置 0
    int startX = 0, startY = 0, finishX = 0, finishY = 0;       // 起点终点坐标的输入
    cin >> startX >> startY >> finishX >> finishY;
    int tempX = 0, tempY = 0;                                   // 输入障碍物坐标
    for (int i=0; i<T; i++)
    {
        cin >> tempX >> tempY;
        maze[tempX-1][tempY-1] = 1;
    }
    mazePathfinding(maze, N, M, startX-1, startY-1, finishX-1, finishY-1);      //DFS 递归实现
    cout << counter;
    return 0;
}

​ 这个递归实现的逻辑非常简单:首先判断是否到达终止条件,如果没有,那么尝试往四个方向走,也就是进入下一层递归。

# 递归实现的特点

# 优点

- 实现简单而直观

# 缺点

- 面对大规模问题时容易造成深层递归,甚至造成栈溢出

未完待续