题目来源:https://www.dotcpp.com/oj/problem1672.html
小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。
小明只能向上下左右四个方向移动。
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。
对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。
样例输入:
1
5 5
S-###
-----
##---
E#---
---##
样例输出
9
/* 广度优先搜索双队列(QueX和QueY)分别存储横纵坐标
1、输入迷宫数据到二维字符型数组map
2、创建跟踪数组step记录每节点步数
3、创建步伐数组
4、用两个队列分别记录可用点的x坐标和y坐标
5、当节点的x坐标=ex且y坐标=ey时从计步数组step返回步数,否则返回-1*/
#include<stdio.h>
#include<string.h>
#define SIZE 100
//为了省事都扔在这里了,函数调用的时候一个指针就行了
typedef struct MazeBFS{
int QueX[SIZE*SIZE];
int QueY[SIZE*SIZE];
int step[SIZE][SIZE];
char map[SIZE][SIZE];
int head,tail;
int N,M;
int sx,sy,ex,ey;
}Maze;
void MazeInit(Maze *maz);//结构体初始化
void InputMap(Maze *maz);//输入迷宫地图
void InOutPoint(Maze *maz);//搜索入口和出口坐标
void QueInit(Maze *maz);//坐标队列初始化
int PathFinding(Maze *maz);//广度优先-搜索路径
int main(int argc,char const *argv[]){
Maze maz;
int i,path,T;
scanf("%d",&T);
while(T--){
MazeInit(&maz);//输入新地图之前清零存储区
scanf("%d%d",&maz.N,&maz.M);
InputMap(&maz);
InOutPoint(&maz);
QueInit(&maz);
path = PathFinding(&maz);
printf("%d\n",path);
}
return 0;
}
//初始化结构体,所有存储单元清零
void MazeInit(Maze *maz){
memset((void *)maz,0,sizeof(Maze));
}
//输入N行地图数据到map
void InputMap(Maze *maz){
int i;
for(i = 0;i < maz->N;i++){
scanf("%s",maz->map[i]);
}
}
//找到入口点(sx,sy)和出口点(ex,ey)
void InOutPoint(Maze *maz){
int i,j;
for(i = 0;i < maz->N;i++){
for(j = 0;j < maz->M;j++){
if(maz->map[i][j] == 'S'){
maz->sx = i;
maz->sy = j;
}
if(maz->map[i][j] == 'E'){
maz->ex = i;
maz->ey = j;
}
}
}
}
//初始化坐标队列和计数矩阵
void QueInit(Maze *maz){
maz->head = 0;
maz->tail = 0;
maz->QueX[maz->tail] = maz->sx;
maz->QueY[maz->tail] = maz->sy;
maz->tail++;
maz->step[maz->sx][maz->sy] = 1;
}
//四个方向寻路
int PathFinding(Maze *maz) {
int xp[] = {-1,1,0,0};//xp和yp通过给坐标加减一以实现移动
int yp[] = {0,0,-1,1};//比如xp[0]yp[0]表示i坐标减一,而j坐标不变
int tx,ty;
int nx,ny;
int i;
while(maz->head != maz->tail){
tx = maz->QueX[maz->head];
ty = maz->QueY[maz->head];
maz->head++;
if(tx == maz->ex&&ty == maz->ey){
return maz->step[maz->ex][maz->ey] -1;
}
for(i = 0;i < 4;i++){
nx = tx + xp[i];//-1,1,0,0
ny = ty + yp[i];//0,0,-1,1
if(nx >= 0&&nx < maz->N&&ny >= 0&&ny < maz->M&&//坐标不越界 并且
maz->map[nx][ny] != '#'&&maz->step[nx][ny] ==0){//该点可走并且没走过
maz->QueX[maz->tail] = nx;
maz->QueY[maz->tail] = ny;//新可用点坐标入队列
maz->tail++;
maz->step[nx][ny] = maz->step[tx][ty] +1;//相应点计数器加一
}
}
}
return -1;
}