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![](https://img2023.cnblogs.com/blog/3074711/202303/3074711-20230306172923548-1993071980.png)
作用:结束这一次的递归,回溯,即返回上一次递归
第二个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是舍弃时间换取空间