问题描述
参考上图所示迷宫,编写算法求一条从入口到出口的有效路径。
- 图中阴影方块代表墙(不可行走),白色方块代表通道(支持行走)。
- 所求路径必须是简单路径,即所求得的路径上不能重复出现同一通道块。
算法分析
初步分析
通常采用穷举法,即从入口出发,顺某一方向向前探索,若能走通,则继续往前走;否则沿原路返回,换另一个方向继续探索,直到探索到出口为止。为了保证在任何位置都能原路返回,显然需要用一个先进后出的栈来保存从入口到当前位置的路径。
求迷宫中一条路径的算法的基本思路是:
如果当前位置“可通”,则纳入“当前路径”,并继续朝下一个位置探索,即切换下一个位置为当前位置,如此重复直至到达出口;如果当前位置不可通,则应沿“来向”退回到前一通道块,然后朝“来向”之外的其他方向继续探索;如果该通道块的四周4个方块均不可通,则应从当前路径上删除该通道块。
所谓下一位置指的是当前位置四周(东、南、西、北)4个方向上相邻的方块。**
具体流程
1.声明一个结构体patch表示每一个方块,含有两个成员:
(1)int type: 1-通道;0-墙;
(2)int flag: 1-未走;0-已走;-1-不可走。
2.创建一个矩阵表示迷宫,元素类型为结构体patch。
3.创建一个栈,用于存储当前路径依次所经过的每个patch的坐标信息(x, y)。
4.从当前位置cur出发(cur初始化为起点位置),然后基于cur按“东-南-西-北”4个方向顺序依次试探,即按选定的试探方向往前进一个patch到达next位置:
(1)若next“可走”,则将cur入栈,同时将cur对应patch的flag更新为0,然后将cur更新为next,然后重复4;
(2)若next“不可走”,则改变试探方向基于cur前进一个patch获取新next,然后重复(1);
(3)若cur的“东-南-西-北”4个方向均“不可走”,则代表当前位置cur对应patch不可通,将cur对应patch的flag设为-1,执行出栈操作,并将cur更新为出栈元素对应的位置,将新cur对应patch的flag更新为1,然后重复4。
(4)若next等于终点,则将cur和next均入栈并将二者对应patch的flag更新为0,寻找有效路径结束。
(5)寻找过程中,若当前位置cur重新回退至起点位置,代表所给迷宫无解。
5.栈内存储的从“栈底元素 – 栈顶元素”对应的patch序列即为有效路径。
代码实现
step1 : 结构体定义与创建
#include
using namespace std;
#define MaxMazeSize 40 /* 迷宫的最大行列*/
#define MaxStackSize 100 /*栈的最大容量*/
/*声明一个结构体表示patch的坐标信息*/
typedef struct
{
int x, y;
} Position;
/* 声明一个结构体patch表示每一个方块 */
typedef struct
{
int type = 0; // 0-墙;1-通道
int flag = 1; // 0-已走;1-未走(可走);-1-不可走(禁走)
} Patch;
/*声明栈结构体*/
typedef struct
{
Position data[MaxStackSize];
Position *top = data; // 默认初始化栈
} PosStack;
PosStack S; // 创建栈保存有效路径坐标信息
Patch maze[MaxMazeSize][MaxMazeSize]; // 创建迷宫(二维列表):元素类型为结构体patch
int rows, cols; // 迷宫的行数及列数
Position startPos, endPos; // 起点坐标 + 终点坐标
step2 : 迷宫初始化
/*初始化迷宫*/
void InitMaze()
{
int walls;
cout > rows >> cols;
int k = 0;
while (k > walls; // 用户自定义设置内部区域墙的数量
cout > x >> y;
maze[x][y].type = 0;
maze[x][y].flag = -1;
}
}
step3 : 展示迷宫
/*展示迷宫结构*/
void DisplayMaze(int rows, int cols)
{
for (int i = 0; i
step4 : 判断某个位置对应的方块是否可走
/*给定坐标,判断该坐标对应patch是否可走*/
bool JudgeNext(Position next)
{
if (next.x rows - 1)
{ // 判断该坐标是否越界
return false;
}
if (maze[next.y][next.x].type == 0)
{ // 判断该坐标对应patch是墙还是通道
return false;
}
if (maze[next.y][next.x].flag
step5 : 迷宫求解-寻找有效路径
/*迷宫求解*/
bool FindMazePath()
{
bool reFlag = false;
Position curPos = startPos; // 当前位置
Position nextPos; // 下一试探位置
int direction;
while (1)
{
direction = 1;
while (direction 4) // 当前位置不可通
{
maze[curPos.y][curPos.x].flag = -1;
curPos = *(--S.top); // 执行出栈操作,并将当前位置更新为出栈patch对应位置
maze[curPos.y][curPos.x].flag = 1;
}else{ // next可走
*(S.top++) = curPos;
maze[curPos.y][curPos.x].flag = 0;
curPos = nextPos;
}
if(reFlag){
break; // 抵达终点,找到有效路径,终止寻找
}
if((curPos.x == startPos.x) && (curPos.y == startPos.y)){
cout
step6 : 主方法调用
int main()
{
InitMaze();
cout > startPos.x >> startPos.y;
cout > endPos.x >> endPos.y;
if(FindMazePath()){
cout
运行效果
case1 : 迷宫有解
case2 : 迷宫无解
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.e1idc.net