迷宫问题求解

来源:互联网 发布:算法引论 中文版 pdf 编辑:程序博客网 时间:2024/06/08 08:54

如图,用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;}
提示:在进行测试的时候,可以将表示迷宫的矩阵保存在文件中,需要的时候打开即可,最重要的是修改方便,所以建议使用这种方法。


原创粉丝点击