DFS

DFS主要思想:1.终点,2.回溯。

一、对于终点,我们要对其做一个特殊的处理也就是对结果的处理,处理完之后结束这一次的递归,即开始这一次递归的回溯

二、回溯,有很多人都卡在这里。以我个人学习的经历来谈谈 --> 回溯就是返回上一次递归,然后执行递归语句下没有执行完的语句。这里注意,要标记,否则会重复,导致无法出递归

拿这段代码来解释解释什么叫返回上一次递归,然后执行递归语句下没有执行的语句。

在这一段代码中我们能看到在满足条件(!vis[xx][yy] && ve[xx][yy] == 1)首先给这个点坐标做了标记,即(vis[xx][yy] = 1)然后就重新进入了dfs这个函数,那么有人就会问:既然重新进入了dfs这个函数,那么(vis[xx][yy] = 0)一步不就走不了?

这就是为后边回溯所留的,即递归语句下没有执行的语句就是(vis[xx][yy] = 0)以及for()循环,当找到最终的答案后,会逐步回溯,即返回上一次递归,去实现这一过程。

可能还是会有疑问,什么叫返回上一次递归?这就好像是我在 i = 2 次递归找到最终答案后,回溯,这就回到了 i = 1 次递归,去实现 i = 1 次递归中的递归语句下没有执行完的语句。

可以通过调试去试试这个过程,更加方便理解上边所说的过程

再来说说在这段代码中两个 return 的作用。首先是第一个 return

作用:结束这一次的递归,回溯,即返回上一次递归

第二个return

结束dfs函数

例子

迷宫问题
/*

  • 默认起点为(1,1),给出迷宫和终点,问到终点最少要几步路程
  • 例如:
  • 5 4
  • 4 3
  • 1 1 2 1
  • 1 1 1 1
  • 1 1 2 1
  • 1 2 1 1
  • 1 1 1 2
  • 结果为7
    */

CODE

#include <bits/stdc++.h>
using namespace std;

int n,m,mi=INT32_MAX;
int p,q;
int ve[100][100],vis[100][100];
int dx[5] = {0,-1,0,1,0};
int dy[5] = {0,0,1,0,-1};
void dfs(int x,int y,int step){
    if(x == p && y == q){
        if(step < mi)mi = step;
        return;
    }
    for (int i = 1; i <= 4; i++) {
        int xx,yy;
        xx = x+dx[i];
        yy = y+dy[i];
        if(!vis[xx][yy] && ve[xx][yy] == 1){
            vis[xx][yy] = 1;
            dfs(xx,yy,step+1);
            vis[xx][yy] = 0;
        }
    }
    return;
}
int main(){
    cin >> n >> m;
    cin >> p >> q;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++) {
            cin >> ve[i][j];
        }
    }
    vis[1][1] = 1;
    dfs(1,1,0);
    cout << mi << endl;
    return 0;
}

这里注意:
DFS算法是将图中所有能走的位置都走了一遍
DFS是舍弃时间换取空间

posted @ 2023-03-06 18:19  TFOREVERY  阅读(67)  评论(0编辑  收藏  举报