问题描述:
给定一个M×N的迷宫图,求一条从指定入口到出口的路径。假设迷宫图如图所示(M=10,N=10),其中的方块图表示迷宫。对于图中的每个方块,用空白表示通道,用阴影表示墙。要求所求路径必须是简单路径,即在求得的路径上不能重复出现同一通道块。
给定一个M×N的迷宫图,求一条从指定入口到出口的路径。假设迷宫图如图所示(M=10,N=10),其中的方块图表示迷宫。对于图中的每个方块,用空白表示通道,用阴影表示墙。要求所求路径必须是简单路径,即在求得的路径上不能重复出现同一通道块。
数据组织:为了表示迷宫,设置一个数组a,其中每个元素表示一个方块的状态,为0时表示对应方块是通道,为1时表示对应方块不可走。为了算法方便,在一般的迷宫外围加了一条围墙。
代码示例:
#include <iostream>
using namespace std;
const int MaxSize = 20; //迷宫最大行、列数
const int StackSize = 100; //顺序栈大小
struct Box //方块结构体类型
{
int i; //方块的行号
int j; //方块的列号
int di; //di是下一可走相邻方位的方位号
};
class Stack //顺序栈类
{
Box *data; //存放栈中方块
int top; //栈顶指针
public:
Stack() //构造函数:栈初始化
{
data = new Box[StackSize];
top = -1;
}
~Stack() //析构函数:释放栈空间
{
delete[] data;
}
bool StackEmpty() //判断栈是否为空
{
return(top == -1);
}
void Push(int x, int y, int d) //进栈一个方块
{
top++;
data[top].i = x; data[top].j = y; data[top].di = d;
}
void GetTop(int &x, int &y, int &d) //取栈顶方块
{
x = data[top].i; y = data[top].j; d = data[top].di;
}
void Pop() //退栈一个方块
{
top--;
}
void Setdi(int d) //修改栈顶元素的di值
{
data[top].di = d;
}
void DispBox() //输出栈中所有方块构成一条迷宫路径
{
int k;
cout << "一条迷宫路径如下:\n";
for (k = 0; k <= top; k++)
{
cout << " (" << data[k].i << "," << data[k].j << ")";
if ((k + 1) % 5 == 0) cout << endl; //每行输出5个方块
}
cout << endl;
}
};
class Maze1 //用栈求解一条迷宫路径类
{
int a[MaxSize][MaxSize]; //迷宫数组
int m, n; //迷宫行列数
public:
void Seta(int mg[][MaxSize], int m1, int n1) //设置迷宫数组
{
int i, j;
m = m1; n = n1;
for (i = 0; i<m; i++)
for (j = 0; j<n; j++)
a[i][j] = mg[i][j];
}
bool mgpath(int xi, int yi, int xe, int ye) //求一条从(xi,yi)到(xe,ye)的迷宫路径
{
int i, j, di, i1, j1;
bool find;
Stack st; //建立一个空栈
st.Push(xi, yi, -1); //入口方块进栈
a[xi][yi] = -1; //为避免来回找相邻方块,将进栈的方块置为-1
while (!st.StackEmpty()) //栈不空时循环
{
st.GetTop(i, j, di); //取栈顶方块,称为当前方块
if (i == xe && j == ye) //找到了出口,输出栈中所有方块构成一条路径
{
st.DispBox();
return true; //找到一条路径后返回true
}
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 (a[i1][j1] == 0) find = true; //找到下一个可走相邻方块(i1,j1)
}
if (find) //找到了下一个可走方块
{
st.Setdi(di); //修改原栈顶元素的di值
st.Push(i1, j1, -1); //下一个可走方块进栈
a[i1][j1] = -1; //为避免来回找相邻方块,将进栈的方块置为-1
}
else //没有路径可走,则退栈
{
a[i][j] = 0; //恢复当前方块的迷宫值
st.Pop(); //将栈顶方块退栈
}
}
return false; //没有找到迷宫路径,返回false
}
};
void main()
{
int mg[][MaxSize] = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 },
{ 1, 0, 0, 1, 0, 0, 0, 1, 0, 1 }, { 1, 0, 0, 0, 0, 1, 1, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 1, 0, 0, 0, 0, 1 },
{ 1, 0, 1, 0, 0, 0, 1, 0, 0, 1 }, { 1, 0, 1, 1, 1, 0, 1, 1, 0, 1 },
{ 1, 1, 0, 0, 0, 0, 0, 0, 0, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } };
Maze1 mz; //创建一个Maze1对象mz
mz.Seta(mg, 10, 10); //设置迷宫数组
cout << "求(1,1)到(8,8)的迷宫路径\n";
if (!mz.mgpath(1, 1, 8, 8)) //求入口为(1,1)出口为(8,8)的迷宫路径
cout << "不存在迷宫路径\n";
}