[题解] POJ 3984 迷宫问题 详解
题目
Description
定义一个二维数组:
int maze[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,
};
它表示一个迷宫,其中的 1 表示墙壁,0 表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
Input
一个5 × 5
的二维数组,表示一个迷宫。数据保证有唯一解。
Output
左上角到右下角的最短路径,格式如样例所示。
Sample Input
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
Sample Output
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
解题思路
这题是迷宫求最短路径问题,由于迷宫的边权都为 1, 所以优先使用宽度优先搜索 BFS
来做
当BFS找到终点时,说明找到了一条最短路径,所以要有一个记录当前路径的方法
*** 判断遍历到终点的方法 ***
if ( tx == 4 && ty == 4 ) return tt - 1;
这里的做法是开一个struct
数组来当队列,里面包含了当前遍历到的点x, y
与当前点的父节点位置(由父节点扩展到点x,y)
找到终点时,我们从终点开始看,找到它父节点在队列中的位置,记录它信息(x, y)
,再把这个父节点当成起始点,再次回溯它的父节点...
将父节点内存储的坐标逐一压入堆栈中,当回溯的父节点位置为-1
时,停止回溯,开始将堆栈中的内容全部弹出打印。
注释代码
#include <iostream>
#include <stack>
#include <cstdio>
using namespace std;
const int N = 30;
typedef pair<int, int> PII;
/* 堆栈 stack 的元素为 pair ,以 .first 和 .second 的方式访问 pair 内的两个元素 */
stack<PII> stck;
struct stu {
int x;
int y;
int p; /* p 即为 当前点的父节点在队列 q 中的下标 */
} q[N]; /* q 即为 队列, 使用数组来模拟队列 */
/* 存放地图数据 */
int a[10][10];
/* 表示 x, y 这个点是否进入过队列,每个点最多只进入队列一次(优化) */
bool st[N][N];
/* 下一个点的方向 */
int ne[2][4] = { {0, -1, 0, 1 }, {1, 0, -1, 0} };
/* bfs 返回终点在队列中的位置 */
int bfs ( void )
{
int hh = 0, tt = 0; // 队头hh 队尾tt
q[tt++] = { 0, 0, -1 }; // 添加队头元素,父节点设置为-1,表示这是队头
st[0][0] = true; // (0, 0)点已添加进队列
while ( tt > hh ) // 队列不为空则循环
{
struct stu t = q[hh++]; // 取队头元素
/* 枚举四个方向 */
for ( int i = 0; i < 4; i++ )
{
int tx = t.x + ne[0][i];
int ty = t.y + ne[1][i];
/*
三大判断条件
1、tx,ty在边界内
2、当前点的值为 0
3、当前点未被加入过队列
*/
if ( tx >= 0 && ty >= 0 && tx <= 4 && ty <= 4 && !st[tx][ty] && a[tx][ty] == 0 )
{
st[tx][ty] = true;
q[tt++] = {tx, ty, hh - 1}; // 当前队首 - 1即为它的父节点
}
if ( tx == 4 && ty == 4 ) return tt - 1;
}
}
}
int main ( void )
{
/* 将输入数据存入地图中 */
for ( int i = 0; i < 5; i++ )
for ( int j = 0; j < 5; j++ )
cin >> a[i][j];
int t = bfs(); // 接收BFS的返回值,此时 t 代表终点在队列 q 中位置
/*
i = t
只要 i != -1,意思就是没有遍历到头节点 就一直循环,
每次循环后更新 i = q[i].p 意思是让 i 变为当前 i 所表示点的父节点的位置
每次循环将当前的坐标压入堆栈
*/
for ( int i = t; i != -1; i = q[i].p )
stck.push ( {q[i].x, q[i].y} );
/*
只要堆栈不为空,就弹出栈顶元素并输出
*/
while ( !stck.empty() )
{
PII i = stck.top();
stck.pop();
printf ( "(%d, %d)\n", i.first, i.second );
}
return 0;
}
输入 / 输出:
如果有写的不好的地方,或者有哪里还没有理解的地方,请积极留言
作者:Jude_Zhang
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用BY-NC-SA 许可协议。转载请注明出处!
支持博主:如果您觉得文章对您有帮助,可以点击文章下方赞一下。您的鼓励是博主的最大动力!
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用BY-NC-SA 许可协议。转载请注明出处!
支持博主:如果您觉得文章对您有帮助,可以点击文章下方赞一下。您的鼓励是博主的最大动力!