📅  最后修改于: 2023-12-03 15:12:45.798000             🧑  作者: Mango
本题为《门》游戏中的一关,要求给出一个矩阵,计算从起点到终点的最短路径,并输出路径及其长度。本题为洛谷 P2958,POJ 1979,UVA 816。
这道题并不是一道图论的题目,而是一道广搜的题目。矩阵中的每个格子都可以看作一个图中的节点,相邻的节点之间可以建立一条边。因此,我们可以借助广搜来解决这个问题。
广搜的流程如下:
在实现广搜的过程中,我们需要借助两个数组来记录节点的路径和步数。
#include <iostream>
#include <queue>
using namespace std;
const int MAXN = 25;
const int MAXM = 25;
int maze[MAXN][MAXM]; // 迷宫
int vis[MAXN][MAXM]; // 标记是否访问过
int dis[MAXN][MAXM]; // 记录路径长度
int pre[MAXN][MAXM][2]; // 记录前驱节点
int n, m; // 迷宫的行数和列数
int sx, sy, ex, ey; // 起点和终点坐标
int dx[] = {-1, 0, 1, 0}; // 上下左右四个方向
int dy[] = {0, 1, 0, -1};
void bfs() {
queue<pair<int, int>> q;
q.push({sx, sy});
vis[sx][sy] = 1;
while (!q.empty()) {
auto t = q.front();
q.pop();
for (int i = 0; i < 4; i++) {
int nx = t.first + dx[i];
int ny = t.second + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (maze[nx][ny] == 1) continue;
if (!vis[nx][ny]) {
q.push({nx, ny});
vis[nx][ny] = 1;
dis[nx][ny] = dis[t.first][t.second] + 1;
pre[nx][ny][0] = t.first;
pre[nx][ny][1] = t.second;
}
}
}
}
void print_path(int x, int y) {
if (x == sx && y == sy) {
cout << '(' << x << ',' << y << ')' << endl;
return;
}
int tx = pre[x][y][0], ty = pre[x][y][1];
print_path(tx, ty);
cout << '(' << x << ',' << y << ')' << endl;
}
int main() {
while (cin >> n >> m) {
if (n == 0) break;
// 读入地图
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> maze[i][j];
}
}
// 读入起点和终点坐标
cin >> sx >> sy >> ex >> ey;
sx--;
sy--;
ex--;
ey--;
// 初始化
memset(vis, 0, sizeof(vis));
memset(dis, 0, sizeof(dis));
memset(pre, -1, sizeof(pre));
// 广搜
bfs();
// 输出结果
cout << "路径长度为:" << dis[ex][ey] << endl;
cout << "路径为:" << endl;
print_path(ex, ey);
}
return 0;
}
本题的解法相对来说比较简单,仅仅需要掌握广搜的基本知识即可。在实现过程中,需要注意一些细节问题,例如坐标的转换以及前驱节点记录的问题。