目录
走迷宫
给定一个 n×m 的二维整数数组,用来表示一个迷宫,数组中只包含 0 或 1,其中 0 表示可以走的路,1 表示不可通过的墙壁。
最初,有一个人位于左上角 (1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 (n,m) 处,至少需要移动多少次。
数据保证 (1,1) 处和 (n,m) 处的数字为 0,且一定至少存在一条通路。
输入格式
第一行包含两个整数 n 和 m。
接下来 n 行,每行包含 m 个整数(0 或 1),表示完整的二维数组迷宫。
输出格式
输出一个整数,表示从左上角移动至右下角的最少移动次数。
数据范围
1≤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
输出样例:
8
解析
如果使用dfs来做的话那么可以找出一条路径,但却不是最短的。因此我们用bfs来做这道题目,使用队列来维护其枚举的点,队列的先进先出的性质确保了只有相同层数的点被考察完了才会开始下一层的考察,这样,当第一次到达终点时,层数一定是最小的,与此同时其它的路径也考察到了这个层数,但是还没到终点。而深搜是一条道走到黑,我们无法保证它选择的那条路径是不是最短的。所以在宽搜层层扫描的情况下,最先到达终点的就是最短路径。
bfs写法
先在四周建一层围墙,防止越界,后面也无需专门去判断
使用stl
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int> PII;
const int N=103;
int g[N][N],d[N][N]; //g存放原地图,d存放该位置是否走过并且记录做过的步数
int n,m;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1}; //模拟每一个位置上下左右四个位置
queue<PII> q;
int bfs() {
q.push({1,1}); //将第一个点放入队列
memset(d,-1,sizeof d); // 以-1代表没有走过
d[1][1] = 0; //0还未走动过,所以置为0
while(!q.empty()) {
PII t = q.front(); //取出队头元素进行操作
q.pop();
for(int i=0;i<4;i++) {
int xx = t.first + dx[i], yy = t.second + dy[i]; //得到队头元素上下左右四个位置的坐标,进行判断,如果可以走并且没走过的话就加入队列,并且记录步数
if(g[xx][yy] == 0 && d[xx][yy] == -1) {
d[xx][yy] = d[t.first][t.second] + 1;
q.push({xx, yy});
}
}
}
return d[n][m]; //到达终点,返回走过步数的数量
}
int main() {
int x;
cin >> n >> m;
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++) {
//给地图四周围上墙壁,后面也就不用特判有没有越界了
if(!i || !j || i==n+1 || j==m+1) {
g[i][j]=1;
continue;
}
scanf("%d",&x);
g[i][j]=x;
}
cout << bfs() << endl;
return 0;
}
使用自己实现的队列而不是stl的队列
#include<iostream>
#include<cstring>
using namespace std;
typedef pair<int,int> PII;
const int N=103;
int g[N][N],d[N][N];
int n,m;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
PII q[N*N]; //用pair<int, int> 数组模拟队列
int bfs() {
int tt=0 ,hh=0; //tt为队列尾,hh为队列头
q[++tt]={1,1};
memset(d,-1,sizeof d);
d[1][1] = 0;
while(hh<=tt) { //表示队列中还有元素
PII t = q[++hh]; //取出队头元素进行搜索
for(int i=0;i<4;i++) {
int xx = t.first + dx[i], yy = t.second + dy[i];
if(g[xx][yy] == 0 && d[xx][yy] == -1) {
d[xx][yy] = d[t.first][t.second] + 1;
q[++tt] = {xx, yy};
}
}
}
return d[n][m];
}
int main() {
int x;
cin >> n >> m;
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++) {
if(!i || !j || i==n+1 || j==m+1) {
g[i][j]=1;
continue;
}
scanf("%d",&x);
g[i][j] = x;
}
cout << bfs() << endl;
return 0;
}
打印路径版本
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
typedef pair<int,int> PII;
const int N=103;
int g[N][N],d[N][N];
int n,m;
int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
queue<PII> q;
PII Prev[N][N];
int bfs() {
q.push({1,1});
memset(d,-1,sizeof d);
d[1][1] = 0;
while(!q.empty()) {
PII t = q.front();
q.pop();
for(int i=0;i<4;i++) {
int xx = t.first + dx[i], yy = t.second + dy[i];
if(g[xx][yy] == 0 && d[xx][yy] == -1) {
d[xx][yy] = d[t.first][t.second] + 1;
Prev[xx][yy]=t; //以坐标为下标将点放进数组
q.push({xx, yy});
}
}
}
//由终点往前推,通过坐标为下标取出路径上的点
int x=n,y=m;
while(x || y) {
auto t = Prev[x][y];
cout << x << " " << y << endl;
x = t.first, y = t.second;
}
return d[n][m];
}
int main() {
int x;
cin >> n >> m;
for(int i=0;i<=n+1;i++)
for(int j=0;j<=m+1;j++) {
if(!i || !j || i==n+1 || j==m+1) {
g[i][j]=1;
continue;
}
scanf("%d",&x);
g[i][j]=x;
}
cout << bfs() << endl;
return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/118464.html