题解:AcWing 844 走迷宫
【题目来源】
AcWing:844. 走迷宫 - AcWing题库
【题目描述】
给定一个 \(n\times m\) 的二维整数数组,用来表示一个迷宫,数组中只包含 \(0\) 或 \(1\),其中 \(0\) 表示可以走的路,\(1\) 表示不可通过的墙壁。
最初,有一个人位于左上角 \((1,1)\) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。
请问,该人从左上角移动至右下角 \((n,m)\) 处,至少需要移动多少次。
数据保证 \((1,1)\) 处和 \((n,m)\) 处的数字为 \(0\),且一定至少存在一条通路。
【输入】
第一行包含两个整数 \(n\) 和 \(m\)。
接下来 \(n\) 行,每行包含 \(m\) 个整数(\(0\) 或 \(1\)),表示完整的二维数组迷宫。
【输出】
输出一个整数,表示从左上角移动至右下角的最少移动次数。
【输入样例】
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
【解题思路】

【代码详解】
《AcWing 844 走迷宫》 #BFS#
// 使用STL队列
#include <bits/stdc++.h>
using namespace std;
const int N = 110; // 定义地图最大尺寸
// 定义节点结构体,存储位置和步数
struct Node
{
int x; // 当前节点的x坐标
int y; // 当前节点的y坐标
int step; // 从起点到当前节点的步数
};
int n, m; // 地图的行数和列数
int g[N][N]; // 存储地图信息(0表示可通行,1表示障碍)
bool vis[N][N]; // 标记数组,记录节点是否被访问过
int dx[4] = {-1, 0, 1, 0}; // 四个方向的x偏移量(上、右、下、左)
int dy[4] = {0, 1, 0, -1}; // 四个方向的y偏移量(上、右、下、左)
queue<Node> q; // BFS使用的队列
// 检查坐标(x,y)是否合法且可通行
bool check(int x, int y)
{
// 检查是否越界
if (x < 1 || x > n || y < 1 || y > m)
return false;
// 检查是否是障碍物
if (g[x][y] == 1)
return false;
// 检查是否已被访问
if (vis[x][y])
return false;
return true;
}
// BFS算法实现,返回从起点到终点的最短步数
int bfs(int x, int y, int step)
{
// 标记起点为已访问
vis[x][y] = true;
// 将起点加入队列
q.push(Node{x, y, step});
// 当队列不为空时循环
while (!q.empty())
{
// 取出队首节点
Node nownode = q.front();
q.pop();
// 如果到达终点,返回当前步数
if (nownode.x == n && nownode.y == m)
{
return nownode.step;
}
// 遍历四个方向
for (int i = 0; i < 4; i++)
{
int nx = nownode.x + dx[i]; // 计算新位置的x坐标
int ny = nownode.y + dy[i]; // 计算新位置的y坐标
// 如果新位置合法且未被访问
if (check(nx, ny))
{
vis[nx][ny] = true; // 标记为已访问
// 将新节点加入队列,步数+1
q.push(Node{nx, ny, nownode.step + 1});
}
}
}
// 如果无法到达终点,返回-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];
// 调用BFS并输出结果
cout << bfs(1, 1, 0) << endl;
return 0;
}
// 数组模拟队列(优先推荐)
#include <bits/stdc++.h>
using namespace std;
const int N = 110; // 定义地图最大尺寸
typedef pair<int, int> PII; // 定义坐标对类型
int n, m; // 地图的行数和列数
int g[N][N]; // 存储地图信息(0表示可通行,1表示障碍)
int d[N][N]; // 存储每个位置到起点的最短距离
PII q[N * N]; // 数组模拟的队列,存储待处理的坐标
// BFS算法实现,返回从起点到终点的最短步数
int bfs()
{
int hh = 0, tt = 0; // 队列头指针和尾指针
q[0] = {0, 0}; // 将起点(0,0)加入队列
memset(d, -1, sizeof(d)); // 初始化距离数组为-1(表示未访问)
d[0][0] = 0; // 起点到自己的距离为0
// 定义四个方向的偏移量(上、右、下、左)
int dx[4] = {-1, 0, 1, 0};
int dy[4] = {0, 1, 0, -1};
// 当队列不为空时循环
while (hh <= tt)
{
auto t = q[hh++]; // 取出队首元素
// 遍历四个方向
for (int i = 0; i < 4; i++)
{
int x = t.first + dx[i]; // 计算新位置的x坐标
int y = t.second + dy[i]; // 计算新位置的y坐标
// 检查新位置是否合法且未被访问
if (x >= 0 && x < n && y >= 0 && y < m && g[x][y] == 0 && d[x][y] == -1)
{
d[x][y] = d[t.first][t.second] + 1; // 更新距离
q[++tt] = {x, y}; // 将新位置加入队列
}
}
}
return d[n - 1][m - 1]; // 返回终点到起点的距离
}
int main()
{
// 输入地图尺寸
cin >> n >> m;
// 输入地图数据
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
cin >> g[i][j];
// 调用BFS并输出结果
cout << bfs() << endl;
return 0;
}
【运行结果】
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
浙公网安备 33010602011771号