问题描述
迷宫的游戏我们应该都有玩过,就是我们不断尝试从起点到达终点的过程,中间会有墙壁阻碍着我们,我们就不得不再另找其路。
给我们一个 n * m 的二维数组,让我们从坐标(0,0)的位置走到坐标(n-1,m-1)的位置,其中0表示通路,1表示墙壁。只能上下左右的走,不可以斜着走。
问题解决
用回溯法(考虑递归):MazeTrack()函数用来递归走迷宫,具体步骤为:
- 首先将当前点加入路径,并设置为已走(可以标记称数字2,或其他的都可以,只要区分0和1即可)
- 判断当前点是否为出口,是则输出路径,保存结果;跳转到4
- 依次判断当前点的上、下、左、右四个点是否可走,如果可走则递归走该点
- 当前点推出路径,设置为可走
代码实现
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <stack>
using namespace std;
typedef struct Position
{
int row;//横坐标
int col;//纵坐标
}PT;
stack<PT> path;//定义一个栈容器,用来记录走过的点
//输出栈里面的坐标路径
void PrintPath(stack<PT>& p)
{
//因为栈是一种先进后出的数据结构
//如果我们按照我么之前的入栈形式出栈的话,走的路径刚好就是相反的了
//我们需要再利用一个栈,把原先的栈path导到rpath里面
stack<PT> rpath;
while (!path.empty())
{
rpath.push(path.top());
path.pop();
}
while (!rpath.empty())
{
PT top = rpath.top();
printf("(%d,%d)\n", top.row, top.col);
rpath.pop();
}
}
//判断是否可以走 是否有通路
bool IsPass(int** maze, int N, int M, PT pos)
{
if (pos.row >= 0 && pos.row < N
&& pos.col >= 0 && pos.col < M
&& maze[pos.row][pos.col] == 0)
{
return true;
}
else
return false;
}
//判断是否找到了通路
bool GetMazePath(int** maze, int N, int M, PT cur)
{
path.push(cur);//把当前位置的点入栈 记录下来
//如果走到了出口,就结束了,返回true
if (cur.row == N - 1 && cur.col == M - 1)
return true;
//走到这里,说明还没有找到出口,探测上下左右四个方向是否可以走
PT next;
maze[cur.row][cur.col] = 2;//走过的点把它赋值成2
//上
next = cur;
next.row -= 1;
if (IsPass(maze, N, M, next))
{
//递归
if (GetMazePath(maze, N, M, next))
return true;
}
//下
next = cur;
next.row += 1;
if (IsPass(maze, N, M, next))
{
//递归
if (GetMazePath(maze, N, M, next))
return true;
}
//左
next = cur;
next.col -= 1;
if (IsPass(maze, N, M, next))
{
//递归
if (GetMazePath(maze, N, M, next))
return true;
}
//右
next = cur;
next.col += 1;
if (IsPass(maze, N, M, next))
{
//递归
if (GetMazePath(maze, N, M, next))
return true;
}
//走到这里,说明上下左右都不可以走了,只能往回退了
path.pop();//出栈 不是我们需要的点
return false;
}
int main()
{
int N, M;//N*M的二维数组
while (scanf("%d%d", &N, &M) != EOF)//允许多次输入
{
//int a[N][M];//变长数组,很多版本不支持
//动态开辟二维数组
int** maze = (int**)malloc(sizeof(int*) * N);
//二维数组的输入
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
scanf("%d", &maze[i][j]);
}
}
PT entry = { 0,0 };//起点坐标 入口
if (GetMazePath(maze, N, M, entry))
{
printf("找到通路了\n");
PrintPath(path);
}
else
printf("没有找到通路\n");
//动态释放二维数组
for (int i = 0; i < N; ++i)
{
free(maze[i]);
}
free(maze);
maze = NULL;
}
system("pause");
return 0;
}