迷宫问题求解

如图,用1表示墙,用0表示通路,entry表示入口,exit表示出口,那么如何找到一条通路,用栈和递归方法都可以实现。

《迷宫问题求解》

一.用栈求解

1.首先给定一个入口点,从入口点开始找。

2.将入口点压栈,以后遇到的每一个合法位置的数据也要压栈,并且标记出来,表示走过的路径。

3.判断哪些点能走通,也就是哪些点可以压栈,分别对当前位置的四个方向进行探测即可。找到能走的方向,循环上述过程。

4.如果四个方向都不通,就要回溯到前一个位置,再探测其他方向,直到有路可走。

5.如果回溯到入口点,则证明没有迷宫没有通路。

6.当走到所给定的出口点时,说明已经走出了迷宫。

#include <stack>
#include <iomanip>

template<size_t M, size_t N>
class Maze
{
public:
	//用给定的数组初始化迷宫
	Maze(int maze[M][N])
	{
		for (size_t i = 0; i < M; i++)
		{
			for (size_t j = 0; j < N; j++)
			{
				_maze[i][j] = maze[i][j];
			}
		}
	}

	//坐标
	struct Pos
	{
		int _row;
		int _col;
	};

	//检测坐标是否合法
	bool CheckAccess(Pos next)
	{
		if (next._row >= 0 && next._row < M 
			&&next._col >= 0 && next._col < N
			&&_maze[next._row][next._col] == 0)  //坐标所表示的值也不能为“墙”
		{
			return true;
		}
		return false;
	}

	//找到一条通路
	bool GetMazePath(Pos entry)
	{
		stack<Pos> path;
		path.push(entry);

		while (!path.empty())
		{
			//栈顶的坐标就是当前坐标
			Pos cur = path.top();
			//走过的路标记为2
			_maze[cur._row][cur._col] = 2;

			//已经找到出口
			if (cur._row == M - 1)
				return true;
			
			//四个方向探测
			//上
			Pos next = cur;
			next._row -= 1;
			if (CheckAccess(next))
			{
				path.push(next);
				continue;
			}

			//右
			next = cur;
			next._col += 1;
			if (CheckAccess(next))
			{
				path.push(next);
				continue;
			}

			//下
			next = cur;
			next._row += 1;
			if (CheckAccess(next))
			{
				path.push(next);
				continue;
			}

			//左
			next = cur;
			next._col -= 1;
			if (CheckAccess(next))
			{
				path.push(next);
				continue;
			}

			Pos back = path.top();
			_maze[back._row][back._col] = 3;
			path.pop();
		}
		return false;
	}

	void Print()
	{
		for (size_t i = 0; i < M; i++)
		{
			for (size_t j = 0; j < N; j++)
			{
				cout << setw(2);
				cout << setiosflags(ios::right);
				cout << _maze[i][j] << "  ";
			}
			cout << endl;
		}
		cout << endl;
	}

protected:
	int _maze[M][N];
};

void TestMaze()
{
	int maze[10][10] =
	{
		{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
		{ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
		{ 1, 1, 0, 1, 0, 0, 0, 0, 1, 1 },
		{ 1, 1, 0, 1, 0, 1, 1, 0, 1, 1 },
		{ 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
		{ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 },
	};

	Maze<10, 10> m(maze);
	Maze<10, 10>::Pos entry;
	entry._row = 1;
	entry._col = 0;

	cout << m.GetMazePath(entry) << endl;
	m.Print();
	cout << endl;

}

《迷宫问题求解》

二.递归求解

递归和用栈求解都需要不断探测四周的通路,但是递归是将下一次要走的位置当作入口点,不断探测递归。同样的,要是方向全不通,则要回溯,递归则是返回上一层。

bool GetMazePathR(Pos entry)
{
	Pos cur = entry;
	_maze[cur._row][cur._col] = 2;
	// 已经找到出口
	if (entry._row == N-1)
	{
		return true;
	}

	Pos next = cur;

	// 上
	next._row -= 1;
	if (CheckAccess(next))
	{
		// 子问题
		if (GetMazePathR(next))
			return true;			
	}
		
	// 右
	next = cur;
	next._col += 1;
	if (CheckAccess(next))
	{
		if (GetMazePathR(next))
			return true;
	}

	// 下
	next = cur;
	next._row += 1;
	if (CheckAccess(next))
	{
		if (GetMazePathR(next))
			return true;
	}

	// 左
	next = cur;
	next._col -= 1;
	if (CheckAccess(next))
	{
		if (GetMazePathR(next))
			return true;
	}

	// 
	_maze[cur._row][cur._col] = 3;
	return false;
}

提示:在进行测试的时候,可以将表示迷宫的矩阵保存在文件中,需要的时候打开即可,最重要的是修改方便,所以建议使用这种方法。

    原文作者:迷宫问题
    原文地址: https://blog.csdn.net/zhangyi_ZY/article/details/76085125
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞