栈的应用——求解迷宫问题

问题描述:
给定一个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";
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值