首页 > 其他分享 >迷宫出口1430 BFS

迷宫出口1430 BFS

时间:2024-07-23 20:28:04浏览次数:21  
标签:Pyx end 1430 int 迷宫 next BFS start 100

题目

test

4
0 0 0 1
0 1 1 0
1 1 1 1
0 0 0 0
1 1 4 3

4
0 0 0 1
0 1 1 0
1 1 1 1
0 0 0 0
1 4 2 4

3
0 1 1
0 0 1
1 0 0
1 1 3 3

BFS解法

一.什么是BFS?

这一节是给不了解BFS同学看的,会的可以跳过(๑╹◡╹)ノ"“”。

这层层往外扩散的玩意叫黏菌,没有脑子会走迷宫!!!
感兴趣的同学可以去哔哩哔哩找找。

概念就不多讲了。类似这样层层往外扩散(搜索)就是BFS。
我们做几个小练习

练习1

从左上角开始扩散式一层层填数字。

我先来٩(๑❛ᴗ❛๑)۶
ok

但是实际上,程序是一步步执行的(一次只能站在一格上出发探索)。

练习2

现在提升一些难度,增加些规则

  1. 到1格后按照上左下右逆时针的次序探索,标上不同数字(边界外不标)。
  2. 已经标过数字的不能再标,按照标记的顺序继续探索,直到标满。

从第1个格子探索标序号

到第2个格子

后面已经标记过的和超出范围的我就不标黄了
到第3个格子

如果你能自己填写完剩下的格子,恭喜,你学会了BFS\(^o^)/~。 接下来用这种走法找出口,动手试试

练习3

从A走到B,用数字标出顺序

我把同一层次的数字标成了相同颜色,看看和你写出来的一样吗

我们走到第10步就能找到出口了。
学会了dfs迷宫找出口的思路,看看核心思路和代码实现

二 .核心思路

  1. 二维数组表示地图,空地为0,障碍物为1。走过的格子需要标记,避免重复探索。
  2. 按某个固定顺序依次探索当下格子的四周。将探索到的格子按顺存储起来。
  3. 按先被存储的格子先行进的顺序,行进到下个格子(先入先出,反手从兜里掏出一个队列)。
  4. 探索到终点结束。全部格子都遍历过找不到终点结束。

三.代码实现

地图表示,输入,结构体表示yx坐标,队列存储路径等不多讲了

#include<iostream>
#include<queue>
using namespace std;
// 方向增量,分别为yx,用现在坐标加上增量得到后面坐标 
int dr[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};//	上下左右

struct Pyx { //	结构体用于存储坐标
	int y;
	int x;
};

//	BFS找出口 
string bfs(Pyx start,Pyx end,int (&map)[100][100],int n) {

}

int main() {
	int n = 0;// 地图大小
	cin>>n;
	int map[100][100] = {0};//	地图

	for(int i = 0; i<n; i++) {
		for(int j = 0; j<n; j++) {
			cin>>map[i][j];
		}
	}
	int ha,la,hb,lb;//	A和B坐标
	cin>>ha>>la>>hb>>lb;

	Pyx start,end;//	题目起点是1,1我设的起点0,0,修正一下 
	start.y = ha-1;
	start.x = la-1;
	end.y = hb-1;
	end.x = lb-1;

	cout<<bfs(start,end,map,n);

	return 0;
}

声明个变量current存储当下所在位置
探索一下四周,可行进的点存进队列里(存入队列只是表示有记录,不代表走过)。

//	BFS找出口
string bfs(Pyx start,Pyx end,int (&map)[100][100],int n) {
	if(map[start.y][start.x]||map[end.y][end.x]) {//如果起点或终点是障碍物,不用判定了
		return "NO";
	}
	bool visited[100][100] = {false};// 用于标记地图上的点是否访问过
	visited[start.y][start.x] = true;// 将起点标记为已访问
	queue<Pyx> path;//	声明一个队列用来储存路径
	path.push(start);//	把起点放入队列


	Pyx current = path.front();//	表示当下访问的点。
	for(int i = 0; i<4; i++) {//	探索4个方向
		int next_y = current.y + dr[i][0];
		int next_x = current.x + dr[i][1];

		if(next_y>=0 && next_y<n && next_x>=0 && next_x<n &&//	限制边界到格子外
		        //	障碍物不访问。探索到存入队列的不能重复访问。
		        map[next_y][next_x] == 0 && !visited[next_y][next_x]) {
			if(next_y == end.y && next_x == end.x) {//	能从通过检测的点找到终点则退出判定 
				return"YES";
			}
			Pyx pyx_next;//	创建节点储存下一步坐标
			pyx_next.y = next_y;
			pyx_next.x = next_x;
			path.push(pyx_next);//	将节点存入队列

			visited[next_y][next_x] = true;//	 存入队列的,就标记一下免得重复存


		}
	}
	path.pop();//	四个方向探索完,把节点弹出去 
}

用一个大循环重复上面的步骤,所有格子都走过后退出。
走过的格子坐标会被弹出队列,即队列为空时退出循环,表示找不到终点。

//	BFS找出口
string bfs(Pyx start,Pyx end,int (&map)[100][100],int n) {
	if(map[start.y][start.x]||map[end.y][end.x]) {//如果起点或终点是障碍物,不用判定了
		return "NO";
	}
	bool visited[100][100] = {false};// 用于标记地图上的点是否访问过
	visited[start.y][start.x] = true;// 将起点标记为已访问
	queue<Pyx> path;//	声明一个队列用来储存路径
	path.push(start);//	把起点放入队列

	while(!path.empty()) {
		
		Pyx current = path.front();//	表示当下访问的点。
		for(int i = 0; i<4; i++) {//	探索4个方向
			int next_y = current.y + dr[i][0];
			int next_x = current.x + dr[i][1];

			if(next_y>=0 && next_y<n && next_x>=0 && next_x<n &&//	限制边界到格子外
			        //	障碍物不访问。探索到存入队列的不能重复访问。
			        map[next_y][next_x] == 0 && !visited[next_y][next_x]) {
				if(next_y == end.y && next_x == end.x) {//	能从通过检测的点找到终点则退出判定
					return"YES";
				}
				Pyx pyx_next;//	创建节点储存下一步坐标
				pyx_next.y = next_y;
				pyx_next.x = next_x;
				path.push(pyx_next);//	将节点存入队列

				visited[next_y][next_x] = true;//	 存入队列的,就标记一下免得重复存
			}

		}
		path.pop();//	四个方向探索完,把节点弹出去
	}
	return "NO";//	循环结束了还没找到终点说明到不了 

}

完整代码

#include<iostream>
#include<queue>
using namespace std;
// 方向增量,分别为yx,用现在坐标加上增量得到后面坐标
int dr[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};//	上下左右

struct Pyx { //	结构体用于存储坐标
	int y;
	int x;
};

//	BFS找出口
string bfs(Pyx start,Pyx end,int (&map)[100][100],int n) {
	if(map[start.y][start.x]||map[end.y][end.x]) {//如果起点或终点是障碍物,不用判定了
		return "NO";
	}
	bool visited[100][100] = {false};// 用于标记地图上的点是否访问过
	visited[start.y][start.x] = true;// 将起点标记为已访问
	queue<Pyx> path;//	声明一个队列用来储存路径
	path.push(start);//	把起点放入队列

	while(!path.empty()) {
		
		Pyx current = path.front();//	表示当下访问的点。
		for(int i = 0; i<4; i++) {//	探索4个方向
			int next_y = current.y + dr[i][0];
			int next_x = current.x + dr[i][1];

			if(next_y>=0 && next_y<n && next_x>=0 && next_x<n &&//	限制边界到格子外
			        //	障碍物不访问。探索到存入队列的不能重复访问。
			        map[next_y][next_x] == 0 && !visited[next_y][next_x]) {
				if(next_y == end.y && next_x == end.x) {//	能从通过检测的点找到终点则退出判定
					return"YES";
				}
				Pyx pyx_next;//	创建节点储存下一步坐标
				pyx_next.y = next_y;
				pyx_next.x = next_x;
				path.push(pyx_next);//	将节点存入队列

				visited[next_y][next_x] = true;//	 存入队列的,就标记一下免得重复存
			}

		}
		path.pop();//	四个方向探索完,把节点弹出去
	}
	return "NO";//	循环结束了还没找到终点说明到不了 

}

int main() {
	int n = 0;// 地图大小
	cin>>n;
	int map[100][100] = {0};//	地图

	for(int i = 0; i<n; i++) {
		for(int j = 0; j<n; j++) {
			cin>>map[i][j];
		}
	}
	int ha,la,hb,lb;//	A和B坐标
	cin>>ha>>la>>hb>>lb;

	Pyx start,end;//	题目起点是1,1我设的起点0,0,修正一下
	start.y = ha-1;
	start.x = la-1;
	end.y = hb-1;
	end.x = lb-1;

	cout<<bfs(start,end,map,n);

	return 0;
}

感兴趣的可以结合着看看另一种dfs解法

标签:Pyx,end,1430,int,迷宫,next,BFS,start,100
From: https://blog.csdn.net/qq_50850080/article/details/140639025

相关文章

  • 迷宫
    第3题   迷宫 查看测评数据信息给一个n×m矩阵迷官c[n][m],第i行第j列的值为c[i][j],机器人jqr在迷宫中迷路了需要帮助。机器人jqr当前在(1,1)的位置,出口在(n,m),这个迷言有一个计数器,只有当计数器的值模(p-1)的余数为0时迷宫出口才会开门(出口没有开门意味着即使在(n,m)的......
  • [SDOI2012] 走迷宫 题解
    [SDOI2012]走迷宫题目描述Morenan被困在了一个迷宫里。迷宫可以视为\(n\)个点\(m\)条边的有向图,其中Morenan处于起点\(s\),迷宫的终点设为\(t\)。可惜的是,Morenan非常的脑小,他只会从一个点出发随机沿着一条从该点出发的有向边,到达另一个点。这样,Morenan走的步数可能......
  • 【普及组】广度优先搜索BFS——到达型搜索问题_C++算法竞赛
    文章目录1.走迷宫例1.洛谷B3625迷宫寻路例2.洛谷P1825[USACO11OPEN]CornMazeS例3.[ABC348D]MedicinesonGrid(AtCoder)2.生活背景下的常见问题例.P3958[NOIP2017提高组]奶酪3.输出路径例.洛谷P6207[USACO06OCT]CowsonSkatesGEnd提示:本文建议有一定......
  • 如何建立一颗二叉树?(数据结构:树 + hash表 / 广搜BFS)
    一个二叉树,树中每个节点的权值互不相同。现在给出它的后序遍历和中序遍历,请你输出它的层序遍历。输入格式第一行包含整数 N,表示二叉树的节点数。第二行包含 N 个整数,表示二叉树的后序遍历。第三行包含 N 个整数,表示二叉树的中序遍历。输出格式输出一行 N 个整数,......
  • 【C++BFS 回溯】756. 金字塔转换矩阵
    本文涉及知识点C++BFS算法C++回溯LeetCode756.金字塔转换矩阵你正在把积木堆成金字塔。每个块都有一个颜色,用一个字母表示。每一行的块比它下面的行少一个块,并且居中。为了使金字塔美观,只有特定的三角形图案是允许的。一个三角形的图案由两个块和叠在上面的单......
  • 图——图的遍历(DFS与BFS算法详解)
    前面的文章中我们学习了图的基本概念和存储结构,大家可以通过下面的链接学习:图的定义和基本术语图的类型定义和存储结构这篇文章就来学习一下图的重要章节——图的遍历。目录一,图的遍历定义:二,深度优先搜索(DFS)连通图的深度优先遍历邻接矩阵法实现DFS邻接表法实现DFSD......
  • 迷宫守卫 题解
    给个题目链接:迷宫守卫。下面直接开始讲了。发现一个事情,省选的题已经不怎么考板子难度很高的题了,现在考的都是思维难度非常高的题。首先,我们考虑字典序的性质,如果第一位劣,那么后面无论多优都没用,所以我们要优先满足靠前的位置。于是我们考虑使用二分来找出第一个数,后面以此类......
  • 【C++BFS算法】752 打开转盘锁
    本文涉及知识点C++BFS算法LeetCode752打开转盘锁你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字:‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’。每个拨轮可以自由旋转:例如把‘9’变为‘0’,‘0’变为‘9’。每次旋转都只能旋......
  • D-走一个大整数迷宫(牛客月赛97)
    题意:给两个n行m列的矩阵a和b,计数器,只有当计数器的值模(p-1)时出口才打开,要从左上走到右下,求最快多久走出迷宫。分析:无论2的bij次方有多大p的2的bij次方的次方取模(p-1)都为1,所以cij=aij。用bfs搜索最短路径代码:#include<bits/stdc++.h>usingnamespacestd;structA{   i......
  • 广度(宽度)优先搜索(遍历)bfs详解
    简介    广度优先搜索(遍历)是一种在图的搜索遍历中较常见的算法。它的时间复杂度通常要比深度优先搜索(遍历)要低很多,尤其是最短路。这是因为深度优先的思想是走一条路要把它走到底再去考虑别的路,如果一开始走错了,后面会浪费很多时间在死胡同上,而且递归的方法本来就需要......