广搜(BFS)

在我们日常刷题的过程中,我们会通过遍历来获取自己想要的数组,搜索算法就是典型的一种。
而搜索算法中也分深搜(DFS),广搜(BFS),而今天,我们来说说广搜。

什么是广搜

广搜全称叫广度优先搜索,或叫宽度优先搜索,简称BFS。人如其名,他不像深搜一路干到底,而是一层一层的搜索,如图在这里插入图片描述
当然,广搜有很多种,这只是广搜和二叉树的结合,不过大体就是像这样,一层一层的搜索

广搜原理及其伪代码

在这里插入图片描述
如上图,是广搜全过程(无重复搜索)
我来给大家解读下
刚开始时是1号位,由于广搜是一层层的搜索,所以搜完2号位后不能着急搜2号位的其他点,而是要把1号位能搜完的全部搜完,于是我们搜3号位。这时1号位搜完了,所以我们可以搜其他位了,我们可以先搜3号位,同搜1号位,4号位和5号位搜完了…直到最后61号位和60号位搜完了,到62号位了,最后结束。
【分析】我们口述时是直接更换搜索位置的,这对于我们人来说很轻松,但是大家想过没有,这用c++该怎么实现呢?其实很简单,用数组模拟就行,用一个变量记录现在搜的是谁,如果搜完了,就跳到下一位。
代码如下(注:此代码只是表达思路,并不是伪代码):

int ab[1050];
int head=0;
if(搜完了){
head++;
} 
else{
	for(){
		继续搜索 加入数据
	}
}

不过虽然数组模拟通俗易懂,但对于某些情很极端,如你要加入1千万的数据,数组就存不下了,对于这种数组存不下的情况该怎么办呢?这时,我们得先冷静下来,思考,为什么数组存不下,就是因为删除的部分没有删除数据,只要把前面的数删了,问题就解决了,哎!恰好c++的STL里面的队列可以解决此问题,而且和数组差不多,甚至会比数组模拟更好用
好,看代码(注:此代码只是表达思路,并不是伪代码

queue<int>q;
初始化
如果队列不为空{
   int f=q.front();q.pop();//弹出
   if(满足答案){
   return ...; 
   } 
   搜索{ 
        if(满足条件){
        q.push(...); 
		} 
   } 
}

好的我们终于分析完了,总结:广搜一般用队列,如果数据量较小,就用数组模拟(尽量用队列),
如果队列不为空(就是没搜完)就继续搜,搜完一个弹出队列,如果满足答案就返回(BFS函数大多是用返回值int),否则慢慢搜答案。对于搜到的答案如果满足条件就入队
好的伪代码如下

int bfs(变量){
	queue<类型>q;
	初始化
	while(!q.empty()){  //队列不为空 
		类型 f=q.front(),q.pop();
		if(判断能否返回)
		{
			return ;  //返回 
		 } 
		 for(枚举(搜索)){
		    判断{
		    初始化搜索结果 
			q.push(...);  //加入 
			如果能返回就直接返回 
			} 
		 }
	} 
	return -1;  //返回不了 
}

广搜经典例题

知道广搜原理后就可以上手了!

1330:【例8.3】最少步数

【题目描述】
在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100×100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。

【输入】
A、B两点的坐标。

【输出】
最少步数。

【输入样例】
12 16
18 10
【输出样例】
8
9

【分析】很明显是道广搜题(因为我们需要多重考虑),重!!!:我们在搜索时一定要方向数组,而且也要标记数组,毕竟会走重复路就会超时(亲测)。这时我们也要用到结构体了,因为考虑到了步数,位置,我们需要结构体里的变量标记,不然得至少开三维数组

#include<bits/stdc++.h>
using namespace std;
int xy[][2]={{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{2,2},{2,-2},{-2,-2},{-2,2}};
//方向数组与标记数组
int flag[105][105];
//结构体
struct node{
	int x,y;
	int step;//步数
};
int bfs(int x,int y){
	queue<node>q;
	//初始化
	node cs;   
	flag[x][y] = 1;
	cs.step = 0 , cs.x = x , cs.y = y;
	q.push(cs);
	while(!q.empty()){
		node f = q.front(); q.pop();  
		if(f.x == 1 && f.y == 1){
			return f.step;
		}
		for(int i = 0;i < 12;i++){//搜索
			int xx = f.x + xy[i][0];
			int yy = f.y + xy[i][1];
			//数据判断
			if(xx >= 1 && xx <= 100 && yy >= 1 && yy <= 100 && flag[xx][yy] == 0)
			{
				node nw;
				flag[xx][yy] = 1;
				nw.x = xx , nw.y = yy , nw.step = f.step + 1;
				if(xx == 1 && yy == 1){
					return nw.step;
				}
				q.push(nw);
			}
		}
	}
}
int main()
{
int x,y;
cin >> x >> y;
cout << bfs(x , y) << endl;
memset(flag,0,sizeof(flag));  //调用俩次,flag清0
cin >> x >> y;
cout << bfs(x , y) << endl;
	return 0;
}

1254:走出迷宫

【题目描述】
当你站在一个迷宫里的时候,往往会被错综复杂的道路弄得失去方向感,如果你能得到迷宫地图,事情就会变得非常简单。

假设你已经得到了一个n×m
的迷宫的图纸,请你找出从起点到出口的最短路。

【输入】
第一行是两个整数n
和m
(1≤n,m≤100
),表示迷宫的行数和列数。

接下来n
行,每行一个长为m
的字符串,表示整个迷宫的布局。字符‘.’表示空地,‘#’表示墙,‘S’表示起点,‘T’表示出口。

【输出】
输出从起点到出口最少需要走的步数。

【输入样例】
3 3
S#T
.#.

【输出样例】
6
【分析】经典广搜,方向数组,标记数组,大力枚举,结构体一条龙

#include<bits/stdc++.h>
using namespace std;
int n,m;
int flag[105][105];  //标记数组
char mp[105][105];
int dx[] = {0 , 0 , 1 , -1};  //方向数组
int dy[] = {1 , -1 , 0 , 0};
struct node{   //结构体
	int x,y;
	int step;
};
int bfs(int lx,int ly,int zx,int zy){
	queue<node>q;
	//初始化
	node g; 
	flag[lx][ly] = 1;
	g.x = lx,g.y = ly,g.step = 0;
	q.push(g);
	while(!q.empty()){
		node f = q.front();
		q.pop();
		if(f.x == zx && f.y == zy){  //答案判断
			return f.step;
		}
		//大力出奇迹
		for(int i = 0;i < 4;i++){
			int fx = f.x + dx[i];
			int fy = f.y + dy[i];
			//范围判断
			if(fx >= 1 && fx <= n && fy >= 1 && fy <= m && flag[fx][fy] == 0 && mp[fx][fy] != '#')
			{
				flag[fx][fy] = 1;
				node now;
				now.x = fx , now.y = fy , now.step = f.step + 1;
			    q.push(now);
			    if(fx == zx && fy == zy){  //答案判断
			        return f.step + 1;
		        }
			}
		}
	}
	return -1;
}
int main()
{
cin >> n >> m;
int sx,sy,zx,zy;
for(int i = 1 ;i <= n;i++){
	for(int j = 1;j <= m;j++){
		cin>>mp[i][j];
		if(mp[i][j] == 'S'){   //拿下起点位置
			sx=i;
			sy=j;
		}
		if(mp[i][j] == 'T'){   //拿下终点位置
			zx=i;
			zy=j;
		}
	}
}
cout << bfs(sx,sy,zx,zy);
	return 0;
}

数字转换

给你两个数s,t, 从s开始,每次从小于当前数的质因子中挑选一个数加给当前数,问最少加几次能到达t

输入
第一行输入一个整数T,表示测试组数

接下来T行每行两个整数s,t

输出
对于每组测试数据输出一个最小步数,如果无法到达,输出-1

具体格式见样例输出

样例
输入 1
2
6 12
6 13
输出 1
Case 1: 2
Case 2: -1
提示
约定:
T<=500,1<=s<=100,1<=t<=1000
【分析】这里已经不是搜索题了,但是仍要用广搜的思想(一层层枚举),不过值得注意的是,这里需要用素数筛法+广搜

#include<bits/stdc++.h>
using namespace std;
int s,t;
const int N=1010;
int flag[N];
void init(){   //素数筛
	flag[1]=1;
	for(int i=2;i<N;i++){
		if(flag[i]==0){
			for(int j=i+i;j<N;j+=i){
				flag[j]=1;
			}
		}
	}
} 
int vis[N],dis[N];//vis标记数组,dis答案数组
int bfs(int s,int t){
	queue<int>q;
	q.push(s);
	vis[s]=1;
	dis[s]=0;
	while(!q.empty()){
		int f=q.front();
		q.pop();
		if(f==t){
			return dis[t];
		}
		for(int i=2;i*i<=f;i++){
			if(f%i==0&&flag[i]==0){
				int x=i;
				if(f+x<=t&&vis[f+x]==0){
					vis[f+x]=1;
					q.push(f+x);
					dis[f+x]=dis[f]+1;
				}
			}
			if(f%i==0&&f/i!=i&&flag[f/i]==0){
				int x=f/i;
				if(f+x<=t&&vis[f+x]==0){
					vis[f+x]=1;
					q.push(f+x);
					dis[f+x]=dis[f]+1;
				}
			}
		}
	}
	return -1;
}
int main()
{
init();
int T,ca=1;
cin>>T;
while(T--){
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));  //归0
cin>>s>>t;
cout<<"Case "<<ca<<": "<<bfs(s,t)<<"\n";
ca++;
}
	return 0;
} 

营救计划

易错题警告!!!
在一个n∗m的迷宫里,有一个萌新被困住了,你作为一个久经码场的战士,决定去营救萌新。地图中还会有一些守卫,你必须打败守卫才能通过守卫所在的位置,打败守卫需要花费1分钟,移动一步需要花费一分钟,每次你只能往上下左右某个方向移动一步。问你最少需要花费多少时间才能救到萌新。

输入
第一行输入两个整数 n,m

接下来n行每行输入m个字符

'#'代表障碍物,无法直接通过

'.'代表空地,可以直接通过

'G’代表守卫,你需要打败他才能通过

'M’代表萌新所在的位置

'@'表示你所在的位置

输出
如果可以营救到萌新,就输出最少需要花费的分钟数

如果不可以,输出“You can’t save Mengxin”

样例
输入 1
7 8
#.#####.
#.M#…@.
#…#G…
…#…#.#
#…##…
.#…

输出 1
13
输入 2
2 2
M.
G@
输出 2
2
提示
1<=n,m<=200
【分析】经典广搜,分析什么?于是,一顿小连招,你会,发现错了!为什么错了呢,这是经典广搜,不过是他却是考到了广搜->状态,我们只需分类讨论就行了

#include<bits/stdc++.h>
using namespace std;
const int N=222;
int n,m;
int dis[N][N][2]; //状态数组
int vis[N][N][2];
char mp[N][N];
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
struct node{  
	int x,y,flag;
};
int bfs(int sx,int sy){
	queue<node>q; 
	node t;
	t.x=sx;t.y=sy;t.flag=0;
	q.push(t);
	vis[sx][sy][1]=0;
	dis[sx][sy][1]=0;
     while(!q.empty()){
     	node f=q.front();q.pop();
     	if(mp[f.x][f.y]=='G'&&f.flag==0&&vis[f.x][f.y][1]==0){//特判
     		dis[f.x][f.y][1]=dis[f.x][f.y][0]+1;
     		vis[f.x][f.y][1]=1;
			 f.flag=1;
     		q.push(f);
     		continue;
		 }
     	for(int i=0;i<4;i++){
     		node g;
     		int nowx=f.x+dx[i];
     		int nowy=f.y+dy[i];
     		g.x=nowx;g.y=nowy;
			 if(nowx<0||nowx>=n||nowy<0||nowy>=m||mp[nowx][nowy]=='#')
			 {
			 	continue;
			 }
			 
     			if(mp[nowx][nowy]=='G'){//状态情况考虑
     				if(vis[nowx][nowy][0]==0){
     					vis[nowx][nowy][0]=1;
     					dis[nowx][nowy][0]=dis[f.x][f.y][f.flag]+1;
					    g.flag=0;
					    q.push(g);
					}
			    }
			    else if(mp[nowx][nowy]=='M'){
			    	return dis[f.x][f.y][f.flag]+1;
				}
				else{
					if(vis[nowx][nowy][1]==0){
						vis[nowx][nowy][1]=1;
						dis[nowx][nowy][1]=dis[f.x][f.y][f.flag]+1;
						g.flag=1;
						q.push(g);
					}
				}
		 }
	 }
	 return -1;
}
int main()
{

cin>>n>>m;
int sx,sy;
for(int i=0;i<n;i++){
cin>>mp[i];
	for(int j=0;j<m;j++){	
		if(mp[i][j]=='@'){
			sx=i;
			sy=j;
		}
	}
}
int ret=bfs(sx,sy);
if(ret==-1){
	cout<<"You can't save Mengxin";
}
else{
	cout<<ret;
}
	return 0;
} 

完结!!!撒花!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/423144.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SqlServer配置定时备份

在企业系统环境中&#xff0c;为了确保SQL Server数据库受到意外的人为错误、系统故障、病毒攻击等因素的影响&#xff0c;我们通常会选择定期备份数据库。但是随着时间尺度的拉长&#xff0c;如果每次备份都要去手动执行一次的话&#xff0c;可能会觉得有些麻烦&#xff0c;或…

【《高性能 MySQL》摘录】第 9 章 操作系统和硬件优化

文章目录 9.1 什么限制了MySQL的性能9.2 如何为 MySQL 选择 CPU9.2.1 哪个更好&#xff1a;更快的 CPU 还是更多的 CPU9.2.2 CPU架构9.2.3 扩展到多个CPU和核心 9.3 平衡内存和磁盘资源9.3.1 随机 I/O 和顺序 I/O9.3.2 缓存&#xff0c;读和写9.3.3 工作集是什么9.3.4 找到有效…

JMeter性能测试基本过程及示例

jmeter 为性能测试提供了一下特色&#xff1a; jmeter 可以对测试静态资源&#xff08;例如 js、html 等&#xff09;以及动态资源&#xff08;例如 php、jsp、ajax 等等&#xff09;进行性能测试 jmeter 可以挖掘出系统最大能处理的并发用户数 jmeter 提供了一系列各种形式的…

P4715 【深基16.例1】淘汰赛题解

题目 有&#xff08;n≤7&#xff09;个国家参加世界杯决赛圈且进入淘汰赛环节。已经知道各个国家的能力值&#xff0c;且都不相等。能力值高的国家和能力值低的国家踢比赛时高者获胜。1号国家和2号国家踢一场比赛&#xff0c;胜者晋级。3号国家和4号国家也踢一场&#xff0c;…

node.js最准确历史版本下载

先进入官网:Node.js https://nodejs.org/en 嫌其他博客多可以到/release下载:Node.js,在blog后面加/release https://nodejs.org/en/blog/release/ 点击next翻页,同样的道理

值得一试的五大AI编程助手

AI编程助手已成为开发过程中不可缺少的一部分&#xff0c;因为它们可以协助代码生成、理解、项目搜索以及使用提示或代码执行各种任务。甚至像谷歌Colab和Deepnote这样的云IDE平台也提供AI辅助编程&#xff0c;可以帮助您生成代码并解决问题。 本文将介绍5款值得一试的AI编程助…

外贸福利 PHP源码 WhatsApp 营销 - 批量发件人、聊天、机器人、SaaS 搭建

WhatsApp 营销工具对于外贸人员来说至关重要。随着全球贸易的不断发展&#xff0c;WhatsApp已成为了许多国际贸易商之间沟通的首选工具之一。通过利用WhatsApp营销工具&#xff0c;外贸人员可以轻松地与客户建立联系&#xff0c;传递产品信息&#xff0c;进行价格谈判&#xff…

智能分析网关V4安全帽检测/反光衣检测/通用工服检测算法及应用

TSINGSEE青犀视频智能分析网关V4内置了近40种AI算法模型&#xff0c;支持对接入的视频图像进行人、车、物、行为等实时检测分析&#xff0c;上报识别结果&#xff0c;并能进行语音告警播放。硬件管理平台支持RTSP、GB28181协议、以及厂家私有协议接入&#xff0c;可兼容市面上常…

【Spring Boot 3】的安全防线:整合 【Spring Security 6】

简介 Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多&#xff0c;因为相比与Sp…

巧用眼精星票证识别系统将车辆合格证快速转为结构化excel数据,简单方便

眼精星票证识别系统是一款高效且精准的OCR软件&#xff0c;它的魔力在于能将纸质文档迅速转化为电子文档&#xff0c;并实现自动化的数据结构化处理。它拥有一双"火眼金睛"&#xff0c;无论是各类发票、护照&#xff0c;还是车辆合格证等&#xff0c;都能一一识别。而…

LLC谐振变换器变频移相混合控制MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 基本控制原理 为了实现变换器较小的电压增益&#xff0c;同时又有较 高的效率&#xff0c;文中在变频控制的基础上加入移相控制&#xff0c; 在这种控制策略下&#xff0c;变换器通过调节一次侧开关管 的开关…

数据增加

目录 增加数据 实现数据增加&#xff0c;保存新的内容 注意 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 增加数据 由于 emp 表中的数据对日后的开发依然有用处&#xff0c;所以在讲解更新之前 建议将emp 表数据做一个复制。将…

【C++入门】C++关键字 | 命名空间 | C++的输入输出

目录 0.C与C 1.C的关键字 2.命名空间 2.1域 2.2C中命名冲突问题 2.3命名空间定义 2.4命名空间使用 2.5命令空间的展开&头文件的展开 3.C的输入&输出 3.1cout&cin 3.1<<流插入运算符 3.2>>流提取运算符 0.C与C C是在C的基础之上&#xff…

latex小技巧

目录 如何输入"I"、“II”、“III”、“IV”等大小写罗马数字。 注释&#xff08;单行/多行&#xff09; 单行注释&#xff1a;直接“%” 多行注释&#xff1a; 在TeXstudio: 如何输入"I"、“II”、“III”、“IV”等大小写罗马数字。 \uppercase\expa…

AI-数学-高中-29-样本的数字特征(标准差、方差)

原作者视频&#xff1a;【统计】【一数辞典】3样本的数字特征_哔哩哔哩_bilibili 标准差(s)、方差(S^2)公式&#xff1a;判断数据的稳定性。

数字化转型导师坚鹏:BLM证券公司数字化转型战略

BLM证券公司数字化转型战略 ——以BLM模型为核心&#xff0c;实现知行果合一 课程背景&#xff1a; 很多证券公司存在以下问题&#xff1a; 不知道如何系统地制定证券公司数字化转型战略&#xff1f; 不清楚其它证券公司数字化转型战略是如何制定的&#xff1f; 不知道…

ArmSoM Rockchip系列产品 通用教程 之 Camera 使用

Camera 使用 1. Camera 简介 ArmSoM系列产品使用的是mipi-csi接口的摄像头 ArmSoM-Sige7支持双摄同显&#xff1a; 2. RK3588硬件通路框图 rk3588支持2个isp硬件&#xff0c;每个isp设备可虚拟出多个虚拟节点&#xff0c;软件上通过回读的方式&#xff0c;依次从ddr读取每…

【C语言】熟悉文件顺序读写函数

前言 本篇详细介绍了 文件顺序读写常用函数&#xff0c;快来看看吧~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 ​编辑 文件顺序读写函数 fgetc函数 示例 fputc函数 逐个字符写入 写入26个字母 文…

element-plus+vue3表单含图片(可预览)(线上图片)

一、要实现的效果&#xff1a; 二、如果期间出现这样的效果&#xff08;表格穿透过来了&#xff09;&#xff0c;加上了这行代码就可以了&#xff1a; preview-teleported“true” 如果仅测试用&#xff0c;建议使用线上图片链接的形式&#xff0c;免得本地地址不生效&#xf…

STM32 DMA入门指导

什么是DMA DMA&#xff0c;全称直接存储器访问&#xff08;Direct Memory Access&#xff09;&#xff0c;是一种允许硬件子系统直接读写系统内存的技术&#xff0c;无需中央处理单元&#xff08;CPU&#xff09;的介入。下面是DMA的工作原理概述&#xff1a; 数据传输触发&am…