迷宫问题
问题:用一个二维数组来存储迷宫,数组中的每个元素的值只取0或1,其中0表示此路可通,1表示此路不通。对于上例的迷宫可存储如图。
假定迷宫入口坐标为(1,1)
输出为路径
实现代码如下
/*
迷宫问题
作者:Lumao
版本:2021/3/28 0.0版
方法:C++ 队列 数组 结构体 递归 深度优先
目标:找到地图中的所有走法并输出
要点:记录路径 恢复现场 深搜
小结:拎出一个位置来分析,往哪走,出去了做什么,要回来怎么做
*/
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
#define m 6//地图长
#define n 8//地图宽
int Count = 0;//记录不同走法数量
struct step//坐标类型
{
int x;
int y;
bool operator!=(step&q) //用于后面退回时的函数back_one_step
{
return (x != q.x || y != q.y) ? true : false;
}
};
struct step Move[8] {//step 类型数组Move代表8个前进方向
{0,1},
{1,1},
{1,0},
{1,-1},
{0,-1},
{-1,-1},
{-1,0},
{-1,1}
};
int TheMap[][n+2] = {//初始地图,1表示此路不通,0表示可以通过,外面加一层1为围墙
{1,1,1,1,1,1,1,1,1,1},
{1,0,1,1,1,0,1,1,1,1 },
{1,1,0,1,0,1,0,1,0,1 },
{1,0,1,0,0,1,1,1,1,1 },
{1,0,1,1,1,0,0,1,1,1 },
{1,1,0,0,1,1,0,0,0,1},
{1,0,1,1,0,0,1,1,0,1 },
{1,1,1,1,1,1,1,1,1,1}
};
queue<step>s;//用于记录路径的队列
int Maze[m + 2][n + 2];//当前地图
void initialize(int Maze[m+2][n+2])//初始化地图
{
for (int i = 0; i < m + 2; i++)
for (int j = 0; j < n + 2; j++)
Maze[i][j] = TheMap[i][j];
while (!s.empty())
s.pop();//清空记录的路径
}
void Restore(int Maze[m + 2][n + 2],int x,int y,int loop)//恢复地图
{
int loop_now=loop;//只要把当前loop及loop之前方向数据恢复即可
int j, k;
for (; loop_now >= 0; loop_now--)
{
j = x + Move[loop_now].x;
k = y + Move[loop_now].y;
Maze[j][k] = TheMap[j][k];
}
}
void back_one_step(step last)//从记录路径的队列中去掉最近一次记录的那一步
{
while (s.front() != last)
{
s.push(s.front());
s.pop();
}
s.pop();//去掉last坐标
}
void PrintPath()//打印路径
{
step path;
queue<step>temp;
cout << "Path No."<<++Count<<" :" << endl;
while (!s.empty())
{
path = s.front();
temp.push(path);
cout << "(" << path.x << "," << path.y << ")" << endl;
s.pop();
}//将队列中的路径输出并pop
while (!temp.empty())//恢复队列中存储的路径,因为要继续探索其他路径
{
path = temp.front();
s.push(path);
temp.pop();
}
}
int MazePath(int x, int y)//走迷宫函数
{
step temp;
int j, k;
int loop;//循环8个方向
Maze[x][y] = -1;//标志位置已经到达过
for (loop = 0; loop < 8; loop++)//探索当前位置的八个相邻位置
{
j = x + Move[loop].x;//采用move作为数组名与保留字冲突了,改为Move
k = y + Move[loop].y;
if ((j == m)&&(k == n))//找到出口
{
step out = { m,n };//记录出口到路径中
s.push(out);
PrintPath();//输出路径
cout << endl;
Restore(Maze,x,y,loop);//恢复迷宫
//退一步
back_one_step(out);
//return 1;//表示成功找到路径
continue;//继续循环
}
if (Maze[j][k] == 0)//新位置是否可到达
{
temp.x = j;
temp.y = k;
s.push(temp);//保存该点坐标
MazePath(j, k);//深度优先算法,从当前点重新开始出发
//如果要找出所有出路,则需要一个恢复现场的标记
//结束MazePath(j,k)内的循环遍历后,恢复进入前的环境
//在递归中去除Maze(j,k)的-1标记即可。
Maze[j][k] = 0;
back_one_step(temp);//从路径队列中去掉刚刚记录的那一步
}
}
return 0;
}
int main()
{
initialize(Maze);//初始化地图
MazePath(1, 1);//以(1,1)为入口,若没有输出则说明该地图没有路径
system("pause");
return 0;
}
若认为该代码可以有可以更优化的地方,望不吝指教