一道经典的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;
}
}