走出迷宫题解——BFS图文详解

一道经典的bfs搜索题,我们只需要从起点出发向外搜索,将所有能到达的点标记出来即可
在这道题中的bfs的搜索就像是向迷宫中的起点倒入水,水会逐渐蔓延,水所蔓延到的地方就是能够被搜索到的地方
举个图荔(鼠标绘制略丑)
在这里插入图片描述
假设这就是迷宫,起点是绿点,终点是蓝点,黑点是障碍物
我们创建一个存储坐标的队列
queue<pair<int,int>> g
(queue是一个队列,有两种操作push和pop,push将一个数据放入队列尾,pop将队列头部的数据弹出,pair<int,int>是queue所需要储存的数据类型,pair<int,int>基本等同于)

struct node{
int x,y;
};

设置一个数组bool st[10][10]来对能够到达的点进行标记
pair的第一个int代表这个点的纵坐标,第二个int 代表横坐标
所以源点坐标为{3,2}
我们从起点开始,分别向上下左右四个方向进行移动
首先是向上,搜索到了点{4,2},这个点是普通点,所以把这个点放入queue队列中,同时把st[4][2]涂黑.st[4][2]=true;
对上下左右四个点都进行搜索后图为在这里插入图片描述
为了方便表达,我们将每个点标上号
源点的四个方向都被搜索过了,所以踢出队列,之前被搜索到的点加入到队列
此刻右上角的队列中的点有1 2 3 4
1号点先被搜索到,所以在队列的头部,4号点最后被搜索到,所以在尾部(根据上下左右的顺序搜索的)
接下来将队列中最靠前的数取出来(队头)进行搜索
1号点先是向上搜索,但上方已经是边界,所以向上搜索失败,接下来是向下搜索,下方的点已经被搜索过了,所以也搜索失败st[3][2]=true
接下来向左搜索,搜索成功,标号为5,加入队列
向右搜索,收缩成功,标号为6,加入队列
在这里插入图片描述
此时队列为 2 3 4 5 6,接下来对2进行搜索,原理同上,新搜索到了点7 8 9在这里插入图片描述对3 4 5搜索,均未搜索到新点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
就这样,所有能被搜索到的点都被搜索了一遍
当队列中没有待搜索的点时,BFS结束
下面是代码实现

#include <iostream>
#include <queue>
#include <algorithm>
#include<cstring>
using namespace std;

int dir[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};//用于计算一个点上下左右运动时下标的变化
char a[510][510];//用于记录地图
bool st[510][510];//用于记录哪些格子被搜索过,没搜索过为flase,反之为true;
typedef pair<int, int> pii;

int main() {
	int bi, bj, ei, ej;
	int n, m;
	char ch;
	while (cin >> n >> m) {
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				a[i][j]='#';//有多组测试数据,所以两个数组都要初始化
		memset(st, false, sizeof st);
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++) {
				cin >> ch;
				if (ch == 'E') {
					ei = i, ej = j;//记录起点的坐标和终点的坐标
					a[i][j] = '.';
				} else if (ch == 'S') {
					bi = i, bj = j;
					a[i][j] = '.';
				} else
					a[i][j] = ch;
			}
		}
		queue<pii>q;//队列,用于记录还未进行搜索的点的坐标
		q.push({bi, bj});
		while (q.size()) {
			pii p = q.front();//将队列头的数值赋给p,先进队列的先搜索,后进队列的后搜索
			q.pop();//弹出队列头
			for (int i = 0; i < 4; i++) {//对上下左右四个方向进行搜索
				int ii = p.first + dir[i][0];
				int jj = p.second + dir[i][1];
				if (ii >= 1 && ii <= n && jj >= 1 && jj <= m && a[ii][jj] != '#' && st[ii][jj] == false) {
					q.push({ii, jj});//将这个点搜索到的新点加入到队列中
					st[ii][jj] = true;//标记,说明这个点被搜索到了
				}
			}
		}
		if (st[ei][ej])
			cout << "Yes" << endl;
		else
			cout << "No" << endl;
	}

}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值