迷宫(C++,DFS)

题目描述

给定一个 N × M N \times M N×M 方格的迷宫,迷宫里有 T T T 处障碍,障碍处不可通过。

在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。

输入格式

第一行为三个正整数 N , M , T N,M,T N,M,T,分别表示迷宫的长宽和障碍总数。

第二行为四个正整数 S X , S Y , F X , F Y SX,SY,FX,FY SX,SY,FX,FY S X , S Y SX,SY SX,SY 代表起点坐标, F X , F Y FX,FY FX,FY 代表终点坐标。

接下来 T T T 行,每行两个正整数,表示障碍点的坐标。

输出格式

输出从起点坐标到终点坐标的方案总数。

样例 #1

样例输入 #1

2 2 1
1 1 2 2
1 2

样例输出 #1

1

提示

对于 100 % 100\% 100% 的数据, 1 ≤ N , M ≤ 5 1 \le N,M \le 5 1N,M5 1 ≤ T ≤ 10 1 \le T \le 10 1T10 1 ≤ S X , F X ≤ n 1 \le SX,FX \le n 1SX,FXn 1 ≤ S Y , F Y ≤ m 1 \le SY,FY \le m 1SY,FYm

解题思路:

题目要求就是找出所有从起点到终点的路径,那么就可以采用深度优先搜索来找出每一条路径

我们逐步来实现递归函数

首先,参数列表部分,只需传入x、y用以代表当前坐标

void deep_first_search(int x, int y);

然后,我们来实现递归主体部分

先进行准备工作

创建一个二维数组,来表示地图

再创建一个二维数组,用来标记走过的格子

再再创建一个二维数组,用来存储四个方向

bool map[5][5] = { 0 };//读入地图,0为平地,1为障碍物
bool map_book[5][5] = { 0 };//标记走过的路,0为未走过,1为走过,防止重复
int step[4][2] = //按右、下、左、上四个方向尝试
{
	{0, 1},
	{1, 0},
	{0, -1},
	{-1, 0}
};

准备工作完成,开始实现

for循环尝试四个方向,判断是否可行

若可行,则标记该格子已经走过,然后进入这一个格子,重复以上步骤

此外,在递归返回后不要忘记取消标记

void deep_first_search(int x, int y)//利用深度优先搜索寻找每一条路径,x、y分别代表当前坐标
{
	//递归主体
	for (int i = 0; i < 4; i++)//尝试每一个方向
	{
		int temp_x = x + step[i][0];
		int temp_y = y + step[i][1];
		if (map_book[temp_x][temp_y] || map[temp_x][temp_y])//如果走过或者遇到障碍物,尝试下一个方向
		{
			continue;
		}
		else if (temp_x < 0 || temp_x > N - 1 || temp_y < 0 || temp_y > M - 1)//如果出界,尝试下一个方向
		{
			continue;
		}
		map_book[temp_x][temp_y] = true;//标记为已经走过
		deep_first_search(temp_x, temp_y);
		map_book[temp_x][temp_y] = false;//取消标记
	}
	return;
}

最后,递归停止条件当然就是当前坐标与终点坐标相等了

void deep_first_search(int x, int y)//利用深度优先搜索寻找每一条路径,x、y分别代表当前坐标
{
	//递归结束条件
	if (x == final_x - 1 && y == final_y - 1)
	{
		sum_path++;//找到一条符合条件的路径
		return;
	}
	//递归主体
	for (int i = 0; i < 4; i++)//尝试每一个方向
	{
		int temp_x = x + step[i][0];
		int temp_y = y + step[i][1];
		if (map_book[temp_x][temp_y] || map[temp_x][temp_y])//如果走过或者遇到障碍物,尝试下一个方向
		{
			continue;
		}
		else if (temp_x < 0 || temp_x > N - 1 || temp_y < 0 || temp_y > M - 1)//如果出界,尝试下一个方向
		{
			continue;
		}
		map_book[temp_x][temp_y] = true;//标记为已经走过
		deep_first_search(temp_x, temp_y);
		map_book[temp_x][temp_y] = false;//取消标记
	}
	return;
}

至此,本题核心解题部分说明完毕

完整代码如下

#include <iostream>
using namespace std;

int sum_path = 0;//用于累计总数
int N, M;//分别代表长度和宽度
int final_x, final_y;//代表终点坐标
bool map[5][5] = { 0 };//读入地图,0为平地,1为障碍物
bool map_book[5][5] = { 0 };//标记走过的路,0为未走过,1为走过,防止重复
int step[4][2] = //按右、下、左、上四个方向尝试
{
	{0, 1},
	{1, 0},
	{0, -1},
	{-1, 0}
};

//void out_put_path()//输出路径
//{
//	for (int i = 0; i < N; i++)
//	{
//		for (int j = 0; j < M; j++)
//		{
//			putchar(char(map_book[i][j] + '0'));
//			putchar(' ');
//		}
//		putchar('\n');
//	}
//}

void deep_first_search(int x, int y)//利用深度优先搜索寻找每一条路径,x、y分别代表当前坐标
{
	//递归结束条件
	if (x == final_x - 1 && y == final_y - 1)
	{
		sum_path++;//找到一条符合条件的路径
		//out_put_path();//显示路径
		//putchar('\n');
		return;
	}
	//递归主体
	for (int i = 0; i < 4; i++)//尝试每一个方向
	{
		int temp_x = x + step[i][0];
		int temp_y = y + step[i][1];
		if (map_book[temp_x][temp_y] || map[temp_x][temp_y])//如果走过或者遇到障碍物,尝试下一个方向
		{
			continue;
		}
		else if (temp_x < 0 || temp_x > N - 1 || temp_y < 0 || temp_y > M - 1)//如果出界,尝试下一个方向
		{
			continue;
		}
		map_book[temp_x][temp_y] = true;//标记为已经走过
		deep_first_search(temp_x, temp_y);
		map_book[temp_x][temp_y] = false;//取消标记
	}
	return;
}

int main()
{
	int T, start_x, start_y, obstacle_x, obstacle_y;
	cin >> N >> M >> T;
	cin >> start_x >> start_y;
	cin >> final_x >> final_y;
	for (int i = 0; i < T; i++)
	{
		cin >> obstacle_x >> obstacle_y;
		map[obstacle_x - 1][obstacle_y - 1] = true;//添加障碍物
	}
	map_book[start_x - 1][start_y - 1] = true;//注意要将起点标记
	deep_first_search(start_x - 1, start_y - 1);
	cout << sum_path;
	return 0;
}
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WitheredSakura_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值