844 走迷宫-增改版
给定一个n*m的二维整数数组,用来表示一个迷宫,数组中只包含0或1,其中0表示可以走的路,1表示不可通过的墙壁。
最初,有一个人位于左上角(1, 1)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角(n, m)处,至少需要移动多少次。
数据保证(1, 1)处和(n, m)处的数字为0,且一定至少存在一条通路。
输入格式
第一行包含两个整数n和m。
接下来n行,每行包含m个整数(0或1),表示完整的二维数组迷宫。
输出格式
从出口处一直倒着输出走过的路线坐标。
再一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤n,m≤1001≤n,m≤100
输入样例:
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出样例:
4 4
3 4
2 4
2 3
2 2
2 1
2 0
1 0
8
实现思路:
经典问题-迷宫问题,因为距离等为1,很好地运用bfs算法来实现。
AC代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N=110;
int n,m,G[N][N],d[N][N];//d用于记录到达每个可走坐标的距离
typedef pair<int,int> PII;
queue<PII> q;
PII pre[N][N];
int bfs() {
q.push({0,0});//入队初始坐标
memset(d,-1,sizeof(d));
d[0][0]=0;//初始化初始距离为0 b
int dx[4]= {-1,0,1,0},dy[4]= {0,1,0,-1};// a o c 通过dx dy实现坐标上下左右的移动
while(!q.empty()) { // d
PII p=q.front();
q.pop();
for(int i=0; i<4; i++) {
int x=p.first+dx[i],y=p.second+dy[i];
if(x>=0&&x<n&&y>=0&&y<m&&G[x][y]==0&&d[x][y]==-1) {//如果是可走的道路并且未走到过
d[x][y]=d[p.first][p.second]+1;//距离+1
pre[x][y]=p;//记录当前道路的之前一个道路点的坐标
q.push({x,y});
}
}
}
int a=n-1,b=m-1;
while(a||b) {//当a和b都大于0的时候才是合法下标 输出坐标(x,y)
cout<<a<<" "<<b<<endl;
auto t=pre[a][b];
a=t.first,b=t.second;
}
return d[n-1][m-1];//返回到达出口的最短距离
}
int main() {
cin.tie(0);
cin>>n>>m;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
cin>>G[i][j];
}
}
cout<<bfs()<<endl;
return 0;
}