【数据结构】经典问题——迷宫 回溯法

问题描述

在这里插入图片描述

迷宫的游戏我们应该都有玩过,就是我们不断尝试从起点到达终点的过程,中间会有墙壁阻碍着我们,我们就不得不再另找其路。
给我们一个 n * m 的二维数组,让我们从坐标(0,0)的位置走到坐标(n-1,m-1)的位置,其中0表示通路,1表示墙壁。只能上下左右的走,不可以斜着走。

问题解决

回溯法(考虑递归):MazeTrack()函数用来递归走迷宫,具体步骤为:

  1. 首先将当前点加入路径,并设置为已走(可以标记称数字2,或其他的都可以,只要区分0和1即可)
  2. 判断当前点是否为出口,是则输出路径,保存结果;跳转到4
  3. 依次判断当前点的上、下、左、右四个点是否可走,如果可走则递归走该点
  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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值