题目描述
给定一个 N×M 的网格迷宫 G。G 的每个格子要么是道路,要么是障碍物(道路用 1 表示,障碍物用 0 表示)。
已知迷宫的入口位置为 (x1,y1),出口位置为 (x2,y2)。问从入口走到出口,最少要走多少个格子。
输入描述
输入第 1 行包含两个正整数N,M,分别表示迷宫的大小。
接下来输入一个N×M 的矩阵。若 G_{i,j}=1Gi,j=1 表示其为道路,否则表示其为障碍物。
最后一行输入四个整数 x1,y1,x2,y2,表示入口的位置和出口的位置。
1\leq N,M\leq10^21≤N,M≤102,0\leq G_{i,j}\leq 10≤Gi,j≤1,1\leq x_1,x_2\leq N1≤x1,x2≤N,1\leq y_1,y_2\leq M1≤y1,y2≤M。
输出描述
输出仅一行,包含一个整数表示答案。
若无法从入口到出口,则输出 -1。
输入输出样例
示例 1
输入
5 5
1 0 1 1 0
1 1 0 1 1
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5
输出
8
运行限制
- 最大运行时间:1s
- 最大运行内存: 128M
题解代码
本题是最常见的广度优先搜索。 搜索算法过程如下: 将起始位置加入队列 从队列开头取出一个元素,将这个元素四周可到达并且未被访问的点加入队列 因为队列先进先出的特性,只有当所有距离为 的点被取出队列后,才会遍历距离为1 的点,而距离为 的点能到达的只有距离为 2的点,这也就保证这搜索答案的正确性。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10;
int n,m,g[N][N],vis[N][N];
int x,y,x2,y2;
int nex[4][2]={{0,-1},{-1,0},{1,0},{0,1}};
struct node{
int a,b,c;
};
bool check(int x,int y){ //边界||vis数组为标记数组
if(x<1||x>n||y<1||y>m||!g[x][y]||vis[x][y]) return false;
return true;
}
int bfs(int x,int y){
queue<node> que;
que.push(node{x,y,0}); //这里因为是初始值所以还未开始走所以为0
vis[x][y]=1; //标记
while(!que.empty()){ //队列不为空
node u=que.front(); //返回队列中的第一个元素
que.pop(); //移除队列的第一个元素
if(u.a==x2&&u.b==y2) return u.c; //到达目标位置
for(int i=0;i<4;i++){
int tx=nex[i][0]+u.a;
int ty=nex[i][1]+u.b;
if(!check(tx,ty)) continue;
vis[tx][ty]=1; //标记
que.push(node{tx,ty,u.c+1});
}
}
return -1;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>g[i][j];
cin>>x>>y>>x2>>y2;
cout<<bfs(x,y)<<endl;
return 0;
}