点击查看代码
/*
给出一个n*m的迷宫,其中"*"表示不可通过的墙壁,"."表示平地,"S"表示起点,"T"表示终点。移动过程中,如果当前位置为(x,y)(下标从0开始),且每次只能前往上下
左右(x,y+1)、(x,y-1)、(x-1,y)、(x+1,y)四个位置的平地,n和m都不超过100,求解从起点S到终点T的最少步数
输入样例:
5 5
.....
.*.*.
.*S*.
.***.
...T*
2 2 4 3
输出样例:
11
样例解释:在5*5矩阵中,起点S坐标(2,2),终点T坐标(4,3),从S到达T的步数为11步(S是第0步,T是第11步)
*/
/*
解题思路:
1、因为要求最少步数,而BFS是通过层次的顺序遍历的,因此从起点S开始计算已经遍历的层数,当到达终点T时,已遍历的层数就是最少步数
*/
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#pragma warning(disable:4996)
const int maxn = 100; //矩阵行、列最多100行
struct node {
int x, y; //位置(x,y)
int step; //step是从起点S到该位置的最少步数(即遍历层数)
}S, T, Node; //S是起点,T是终点,Node是临时结点
int n, m; //矩阵行、列数
char maze[maxn][maxn]; //迷宫矩阵
bool inq[maxn][maxn] = { false }; //记录(x,y)是否已入过队
int X[4] = { 0,0,1,-1 }; //增量数组,将(x,y)与它相加,获得其上下左右相邻的4个位置
int Y[4] = { 1,-1,0,0 };
//判断位置(x,y)是否可以访问
bool judge(int x, int y) {
//x或y超出边界,则不可以访问
if (x >= n || x < 0 || y >= m || y < 0) return false;
//(x,y)的元素值是不可通过的墙壁*,或(x,y)已经入过队,则不可以访问
if (maze[x][y] == '*' || inq[x][y] == true) return false;
//其余情况都可以访问
return true;
}
//广度优先搜索
int BFS() {
queue<node> q; //定义队列q
q.push(S); //将起点S入队
while (!q.empty()) { //只要队列q非空,就继续循环
node top = q.front(); //取出队首元素存入top变量中
q.pop(); //队首元素取出后要手动删除
if (top.x == T.x && top.y == T.y) { //如果到达终点,则返回最少步数
return top.step;
}
for (int i = 0; i < 4; i++) { //检查(x,y)的4个相邻位置
int newX = top.x + X[i];
int newY = top.y + Y[i];
if (judge(newX, newY)) { //(newX, newY)可以访问
Node.x = newX, Node.y = newY; //将(newX, newY)存入结点变量Node中
Node.step = top.step + 1; //Node层数是top层数加一
q.push(Node); //将Node入队,等待之后使用
inq[newX][newY] = true; //(newX, newY)已入队,inq[x][y]设为true
}
}
}
return -1; //如果扫描完迷宫无法到达终点T,则最小步数返回-1
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) { //读取迷宫的二维数组
getchar(); //吸收每行后面的换行符
for (int j = 0; j < m; j++) {
maze[i][j] = getchar();
}
}
scanf("%d%d%d%d", &S.x, &S.y, &T.x, &T.y); //读取起点S和终点Y位置
S.step = 0; //初始为第0层,即S到S的最少步数为0
printf("%d\n", BFS()); //进行BFS()查找最少步数
return 0;
}