思路:先把起点S和终点E记录下来,然后进行bfs搜索最短距离,
1、用一个二维数组标记是否已经遍历过
2、两个偏移数组记录方向位置
3、在遍历方向时提前判断 是否到达过、有无越界、 是否是障碍 ,加入队列,当符合条件时,因为这是上一个位置
偏移一个单位的位置,所以把对应二维数组下标的元素的值加1,入队列
4、在while循环中队列不空时取出并记录第一个元素,并把它弹出
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int,int> PII; // 记录坐标
const int N = 205;
char map[N][N]; // 迷宫地图
int X[4] = {0,-1,0,1},Y[4]={-1,0,1,0}; // 坐标偏移数组
int dist[N][N]; // 距离表示从起点到该坐标的距离
int r, c; // 行和列
int bfs(PII start, PII end){
// 不用计算最短,因为bfs广度搜索就是一层一层遍历,先把下一步的全部走一遍,每一层步数只加1,找到终点一定是最小距离
queue<PII> q;
memset(dist, -1 ,sizeof dist); // 对距离数组初始化
dist[start.x][start.y] = 0;
q.push(start);
while(!q.empty()){
PII t = q.front(); // 拿出第一个元素
q.pop(); // 弹出第一个元素
for(int i = 0;i < 4;i++){
int x = t.x + X[i], y = t.y + Y[i];
if(x < 0 || x >= r || y < 0 || y >= c) continue;
if(dist[x][y] != -1 || map[x][y] == '#') continue; // 已经走过或者是障碍物
dist[x][y] = dist[t.x][t.y] + 1; // 走了一步
if(end == make_pair(x,y)) return dist[x][y]; // 到达终点提前退出
// 注意 == 要把{x,y}用make_pair转化为pair类型
q.push({x,y});
}
}
return -1;
}
int main(){
int n; // 总共有几次输入
cin >> n;
while(n--){
cin >> r >> c;
PII start, end; // 起点和终点
for(int i = 0;i < r;i++) scanf("%s",map[i]);
for(int i = 0;i < r;i++)
for(int j = 0;j < c;j++){
if(map[i][j] == 'S') start = {i,j}; // 起点坐标
if(map[i][j] == 'E') end = {i,j}; // 终点坐标
}
int distance = bfs(start,end);
if(distance == -1) printf("oop!\n");
else printf("%d\n",distance);
}
return 0;
}