走迷宫问题
问题概述
如下由'#'和'.'符号组成的图案表示一个迷宫,在这个迷宫中,'.'表示可以走的路径,可以通过,而'#'表示迷宫的墙,是不能穿过的。我们的目的就是要从迷宫的起点走到终点,找出一条合适的路径,当然最短路径最好。
解决方法
算法思想
站在迷宫中的一个位置上,环顾四周,总共有四个方向可以选择,而这每一个方向都有可能成功,同样也有可能失败。在成功的时候我们就需要顺着这条路径往下走,而失败则需要返回上一个可以选择的位置。因此我们需要保存之前走过路径的状态,很容易能够想到递归的解法,使用系统的栈就可以很好的还原状态。
故我们使用递归的解法,在每一个位置上都进行上、下、左、右四个方向的探索,如果这个方向的路径是有效的,则往下递归。无效则跳过,如果四个方向都没有合适的路径,我们就返回上一层(即上一个位置)重新查找。不断尝试,直到从达到终点为止。
C++实现
#include <iostream>
#include <iomanip>
using namespace std;
// 输出迷宫数组
void printMaze(char maze[][12]) {
for (int i = 0; i < 12; ++i) {
for (int j = 0; j < 12; ++j)
cout << setw(2) << maze[i][j];
cout << endl;
}
cout << "\n";
}
// 检测当前位置是否有效
bool vaild(char maze[][12], int row, int col) {
return (row >= 0 && row < 12 && col >= 0 && col < 12
&& maze[row][col] == '.'); // 设置检测'.',避免走回头路
}
// 进行递归查找
void findWay(char maze[][12], int row, int col) {
// 静态初始化位移数组和终点位置,避免每次递归都重新初始化的开支
static const int horizontal[4] = { 1, 0, -1, 0 };
static const int vertical[4] = { 0, 1, 0, -1 };
static const int finalCol = 11, finalRow = 4;
maze[row][col] = 'X'; // 标记当前位置
if (row == finalRow && col == finalCol) {
cout << "\nSuccessful!\n\n"; // 成功找到出口
printMaze(maze);
}
else {
int testCol, testRow;
for (int i = 0; i < 4; ++i) { // 扫描四个方向
testCol = col + horizontal[i];
testRow = row + vertical[i];
if (vaild(maze, testRow, testCol)) // 如果有效则进行递归查找
findWay(maze, testRow, testCol);
}
}
maze[row][col] = '.'; // 还原数组状态
}
int main() {
char maze[12][12] =
{ {'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'},
{'#', '.', '.', '.', '#', '.', '.', '.', '.', '.', '.', '#'},
{'.', '.', '#', '.', '#', '.', '#', '#', '#', '#', '.', '#'},
{'#', '#', '#', '.', '#', '.', '.', '.', '.', '#', '.', '#'},
{'#', '.', '.', '.', '.', '#', '#', '#', '.', '#', '.', '.'},
{'#', '#', '#', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
{'#', '.', '.', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
{'#', '#', '.', '#', '.', '#', '.', '#', '.', '#', '.', '#'},
{'#', '.', '.', '.', '.', '.', '.', '.', '.', '#', '.', '#'},
{'#', '#', '#', '#', '#', '#', '.', '#', '#', '#', '.', '#'},
{'#', '.', '.', '.', '.', '.', '.', '#', '.', '.', '.', '#'},
{'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'} }; // 迷宫数组
printMaze(maze); // 展示迷宫
findWay(maze, 2, 0);
return 0;
}