用栈求解迷宫问题的所有路径及最短路径
题目描述
编写一个程序exp3-5.cpp,改进《教程》3.1.4节中的求解迷宫问题程序,要求输
如图3.9所示的迷宫的所有路径,并求第一条最短路径及其长度。
在本实验中用mg作为迷宫数组,用St数组作为顺序栈,Path数组保存一条迷宫径,将它们都设置为全局变量。
功能算法如下:· mgpath(int xi,int yi,int xe,int ye):求解迷宫问题,即输出从入口(xi,yi)到出口(xe,ye)的全部路径和最短路径(包含最短路径长度)。与《教程》3.1.4节中的求解迷宫问题程序相比,其改进的方法是当找到一条路径时不使用return语句退出,而是出栈一次,重新回溯走另一条路径并输出,并用minlen记录最短路径长度,用Path数组记录最短路径。
· dispapath():输出一条路径并求最短路径。
· dispminpath():输出第一条最短路径及其长度。
运行代码
cpp
#include<stdio.h>
#define M 4
#define N 4
#define MaxSize 100
// 定义迷宫数组
int mg[M + 2][N + 2] = {
{1,1,1,1,1,1},{1,0,0,0,1,1}, { 1,0,1,0,0,1 },
{1,0,0,0,1,1},{1,1,0,0,0,1},{ 1,1,1,1,1,1 } };
// 定义结构体表示路径中的位置和方向
struct {
int i, j;
int di;
} St[MaxSize], Path[MaxSize];//定义栈和存放最短路径的数组
int top = -1; //栈顶指针
int count = 1; //路径数计数
int minlen = MaxSize; //最短路径长度
// 输出一条路径并求最短路径
void dispapath()
{
int k;
// 输出第 count 条路经
printf("%5d:", count++);
for (k = 0; k <= top; k++)
{
// 输出路径中的每个位置
printf("(%d,%d)", St[k].i, St[k].j);
}
printf("\n");
if (top + 1 < minlen) //比较最短路径
{
for (int k = 0; k <= top; k++)
{
// 将当前路径复制到最短路径数组中
Path[k] = St[k];
}
minlen = top + 1;
}
}
// 输出最短路径
void dispminpath()
{
printf("最短路径如下:\n");
// 输出最短路径长度
printf("长度:%d\n", minlen);
printf("路径:");
for (int k = 0; k < minlen; k++)
{
// 输出最短路径中的每个位置
printf("(%d,%d)", Path[k].i, Path[k].j);
}
printf("\n");
}
// 寻找迷宫路径
void mgpath(int xi, int yi, int xe, int ye)
{
int i, j, i1, j1, di;
bool find;
top++;
St[top].i = xi; // 将起始位置压入栈
St[top].j = yi;
St[top].di = -1;
mg[xi][yi] = -1;
while (top > -1)
{
i = St[top].i; j = St[top].j;
di = St[top].di;
if (i == xe && j == ye)
{
dispapath(); // 输出当前路径并更新最短路径相关信息
mg[i][j] = 0;
top--;
i = St[top].i; j = St[top].j;
di = St[top].di;
}
find = false;
while (di < 4 && !find)
{
di++;
switch (di)
{
case 0:i1 = i - 1; j1 = j; break;
case 1:i1 = i; j1 = j + 1; break;
case 2:i1 = i + 1; j1 = j; break;
case 3:i1 = i; j1 = j - 1; break;
}
if (mg[i1][j1] == 0)find = true;
}
if (find)
{
St[top].di = di;
top++;
St[top].i = i1; St[top].j = j1;
St[top].di = -1;
mg[i1][j1] = -1;
}
else
{
mg[i][j] = 0;
top--;
}
}
dispminpath(); // 输出最短路径
}
int main()
{
printf("迷宫所有列途径如下:\n");
// 从左上角 (1,1) 到右下角 (M,N) 寻找路径
mgpath(1, 1, M, N);
return 1;
}
代码思路
一、整体架构
- 首先定义了迷宫的大小
M
和N
,以及一个用于存储路径的结构体和两个用于存储路径的数组St
和Path
。还定义了一些变量用于记录栈顶指针、路径计数和最短路径长度等。 - 定义了三个主要函数:
dispapath
用于输出一条路径并更新最短路径信息;dispminpath
用于输出最短路径;mgpath
是核心函数,用于在迷宫中寻找路径。 - 在
main
函数中调用mgpath
函数,传入起点和终点坐标,启动路径搜索过程。
二、函数功能详解
-
mgpath
函数- 初始化:将起点坐标压入栈
St
,并将起点位置在迷宫数组mg
中标记为已访问(设为 -1)。 - 循环搜索:通过一个
while
循环不断探索迷宫,直到栈为空(top > -1
)。- 检查当前位置是否为终点:如果是终点,调用
dispapath
输出当前路径,并将终点位置在迷宫中重新设为可通行(设为 0),然后调整栈顶指针,准备继续搜索其他路径。 - 寻找下一个可通行位置:如果当前位置不是终点,通过一个内循环不断尝试四个方向(上、右、下、左),找到下一个可通行位置(值为 0 的位置)。如果找到,更新当前位置的方向,将新位置压入栈,并在迷宫中标记新位置为已访问。如果没有找到可通行位置,将当前位置在迷宫中重新设为可通行,然后调整栈顶指针回退。
- 检查当前位置是否为终点:如果是终点,调用
- 输出最短路径:搜索结束后,调用
dispminpath
输出最短路径。
- 初始化:将起点坐标压入栈
-
dispapath
函数- 输出当前路径编号和路径中的每个位置。
- 如果当前路径长度小于最短路径长度,将当前路径复制到
Path
数组中,并更新最短路径长度。
-
dispminpath
函数:输出最短路径的长度和路径中的每个位置。
三、数据结构的运用
- 迷宫数组
mg
:用于表示迷宫的布局,其中1
表示墙壁,0
表示可通行的路径。 - 结构体和数组:定义了一个结构体表示路径中的位置和方向,使用两个数组
St
和Path
分别作为栈和存储最短路径的数组。栈用于存储当前正在探索的路径,而Path
数组用于存储最短路径。
实验小结
一、实验目的与成果
本次实验的目的是在给定的迷宫中找到从起点到终点的路径,并输出所有路径以及最短路径。通过这段代码,成功地实现了以下功能:
- 利用深度优先搜索算法,借助栈数据结构对迷宫进行遍历,找到了从起点到终点的所有可能路径。
- 输出了所有路径的编号以及路径中的每个位置,清晰地展示了探索过程中的各种路径情况。
- 确定并输出了最短路径的长度和具体位置序列,为用户提供了迷宫的最优解。
二、遇到的问题及解决方法
-
路径准确性问题:
- 问题表现:在实验过程中,可能会出现输出的路径不准确或者最短路径计算错误的情况。
- 解决方法:仔细检查代码中的逻辑,特别是在路径长度比较和最短路径更新的部分。确保在判断路径长度和复制路径到最短路径数组时的逻辑正确。同时,检查在探索迷宫过程中对位置的标记和回溯操作是否准确无误。
-
边界处理:
- 问题表现:在探索迷宫时,可能会出现数组越界的错误,尤其是在探索新位置时。
- 解决方法:在代码中添加对新位置的合法性检查,确保新位置在迷宫范围内。在计算不同方向的新位置坐标时,仔细检查是否超出了迷宫的边界,避免出现越界访问的情况。
-
路径唯一性和最短路径选择:
- 问题表现:代码可能会找到重复的路径,并且在存在多条最短路径时可能只输出其中一条。
- 解决方法:可以考虑使用标记数组来记录已经访问过的位置,避免重复探索相同的路径。对于最短路径的输出,可以根据具体需求进行调整,例如输出所有长度相同的最短路径,或者根据特定规则选择其中一条作为最终的最短路径。
三、实验收获与体会
-
数据结构与算法的应用:通过这个实验,深入理解了栈在深度优先搜索算法中的重要作用。栈的后进先出特性非常适合记录路径的回溯过程,能够有效地实现迷宫路径的搜索。同时,对深度优先搜索算法的理解也更加深刻,掌握了如何运用该算法解决实际问题。
-
问题解决能力:在实验过程中,遇到了各种问题,通过分析问题、调试代码和查阅资料,提高了问题解决能力和编程技巧。学会了如何运用逻辑分析和调试工具来找出代码中的错误,并采取有效的措施进行修复。
-
代码优化意识:在解决问题的过程中,意识到代码的性能和可读性可以进一步优化。例如,可以使用更高效的算法来提高搜索效率,或者改进变量命名和添加注释来提高代码的可读性和可维护性。
-
团队合作与交流:如果是在团队中进行实验,可以与团队成员进行交流和讨论,分享解决问题的经验和方法。团队合作可以提高实验的效率和质量,同时也可以学习到其他人的编程思路和技巧。