深度优先搜索DFS

本文介绍了深度优先搜索(DFS)算法,并通过扫地机器人的路径规划问题进行实例解析。DFS是一种遍历或搜索树或图的方法,先沿着一条路径一直探索到底,再回溯寻找其他路径。文章提供了三种不同的C++代码实现,展示了如何在二维网格中按照特定规则进行DFS遍历,最终得到所有可能的路径。
摘要由CSDN通过智能技术生成

什么是DFS

深度优先搜索属于算法的一种,其过程是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。
简单的来说就是:一路走到头,不撞南墙不回头

案例图的遍历

请添加图片描述
遍历上图,图中部分节点之间有路径连接。遍历规则为:深度优先,右手路径优先,不能重复遍历。那么遍历的结果是什么?
ABCDEFGHI

例题 扫地机器人

请添加图片描述

思路

典型的DFS的题。其实优先搜索可以通过if语句来实现(注意不能使用if-else语句 但是此题可以使用if-else语句,因为DFS要全部路径都包括,会退回一些点尝试没有尝试过的路)。既然优先向右来搜索,那么就让y一直+1,直到等于m然后再向下搜索,注意向下搜索在此题中只会走一次。再是向左搜索,依次思路写即可。

AC代码

代码1

#include <iostream>
using namespace std;
//为2维数组赋值 为xy点赋值为k
int n, m;//定义全局变量 使两个函数都可以访问到m与n
int a[1000][1000];
void f(int x, int y, int k) {
	a[x][y] = k; //赋值为k
	//优先向右 其次向下 再向左 最后是下
	//递归的条件不能出边界不能访问已经赋值的点
	//向右
	if (y + 1 <= m && a[x][y + 1] == 0)
		f(x, y + 1, k + 1);
	//向下 仅有一次
	else if (x + 1 <= n && a[x+1][y] == 0)
		f(x + 1, y, k + 1);
	//向左
	else if (y - 1 >= 1 && a[x][y - 1] == 0)
		f(x, y - 1, k + 1);
	//向上
	else if (x - 1 >= 1 && a[x - 1][y] == 0)
		f(x - 1, y, k + 1);
}
int main() {
	cin >> n >> m;
	f(1, 1, 1);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cout << setw(3) << a[i][j];
		}
		cout << endl;
	}
}

代码2

#include <iostream>
using namespace std;
int n, m;
int a[1000][1000];
void f(int x, int y, int k) {
	//递归的条件不能出边界并且不能访问已经赋值的点
	if (x >= 1 && x <= n && y >= 1 && y <= m && a[x][y] == 0) {
		a[x][y] = k; //赋值为k
		//优先向右 其次向下 再向左 最后是下
		//向右
		f(x, y + 1, k + 1);//step1
		//向下
		f(x + 1, y, k + 1);//step2
		//向左
		f(x, y - 1, k + 1);//step3
		//向上
		f(x - 1, y, k + 1);//step4
	}
}
int main() {
	cin >> n >> m;
	f(1, 1, 1);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cout << setw(3) << a[i][j];
		}
		cout << endl;
	}
}

其实可以不用那么麻烦的判断,直接四个递归的。如上述代码,如果比如对于2*2的网格,点(1,3)不能进入step1,就会进入step2.本质上还是DFS的应用。这样的写法每个step的本质就是if判断,点合法则可以进去否则进不去就会进入下一个step。
代码3

#include <iostream>
using namespace std;
int n, m;
int a[1000][1000];
int fx[5] = {0, 0, 1, 0, -1};
int fy[5] = {0, 1, 0, -1, 0};
void f(int x, int y, int k) {
	a[x][y] = k; //赋值为k
	//优先向右 其次向下 再向左 最后是下
	//递归的条件不能出边界不能访问已经赋值的点
	int tx, ty;
	for (int i = 1; i < 5; i++) {
		tx = x + fx[i];
		ty = y + fy[i];
		if (tx >= 1 && tx <= n && ty >= 1 && ty <= m && a[tx][ty] == 0)
			f(tx, ty, k + 1);
	}
}
int main() {
	cin >> n >> m;
	f(1, 1, 1);
	for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			cout << setw(3) << a[i][j];
		}
		cout << endl;
	}
}

思路不变 代码更简洁,效率更高,在递归之前判断就会防止不合法的点进入递归,使效率稍微高那么一点点。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一袍清酒付825

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值