BFS广度优先搜索

好的,上次讲的深搜DFS获得小众好评,我肯定要写一下广搜的blog呀!!!

(其实就是因为上次吐槽的太粗略没脸在水别的。。。)

还是再讲一下定义:

宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止

好的,我来解释一下神吐槽时那超恶心友好的代码是怎么回事,还没看过那篇blog的同志们可以去看一下。https://blog.csdn.net/weixin_43417464/article/details/113844226

搜索常见的迷宫问题(用搜索的)三种形式:

  • 能不能到(最好用深搜)
  • 最短几步到,无边权值,都是单位边权的那种(最好用广搜)
  • 唯一最短路怎么走,无边权值,都是单位边权的那种(最好用广搜)

能不能到之前讲过了,还不会的去看一下呗:https://blog.csdn.net/weixin_43417464/article/details/113061870

直接开讲第二种。

有道这个的模板题,去做一下。http://ybt.ssoier.cn:8088/problem_show.php?pid=1252

先用老少皆宜的深搜做一下:

#include<bits/stdc++.h>
using namespace std;
int minn=0x3f3f3f3f,n,m,ex,ey,vis[101][101],mmap[101][101];
int dis[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
void dfs(int ax,int ay,int depth){
	if(ax==ex&&ay==ey){
		if(depth<minn) minn=depth;
		return ;
	}
	for(int i=0;i<4;i++){
		int dx=ax+dis[i][0],dy=ay+dis[i][1];
		if(dx>=0&&dy>=0&&dx<n&&dy<m&&mmap[dx][dy]&&!vis[dx][dy]){
			vis[dx][dy]=1;
			dfs(dx,dy,depth+1);
			vis[dx][dy]=0;
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++){
			char ch;cin>>ch;
			if(ch=='.') mmap[i][j]=1;
			else mmap[i][j]=0;
		}
	ex=n-1,ey=m-1;
	dfs(0,0,0);
	cout<<minn+1;
	return 0;
}

提交一下......

1,6,10AC,其余的是耀眼的TLE

好吧,只能用广搜了......

先讲一下广搜。

首先,广搜和深搜一样,都得保存可移动点的坐标及深度,也就是到那个点的最少步数。

也就是说,我们必须建立一个结构体,结构体的变量来存储它这个变量所有的信息。

因为我们的广搜要用到队列(原因在神吐槽中讲过了),而队列需要存储每一个点的信息,为了方便查询,我们使用结构体队列。

接着我们需要先把起点的相关信息结构体给塞进队列里,在保证队列不为空的情况下,我们一直while,而到了终点站的时候,就可以直接return了。

while里面和深搜大同小异,先把队列首取出来,找到那些队首点能一步到达的点(照样是dx,dy,边界条件来判断)给它塞到队列里面去,没必要在找一步点是就去看他是不是终点,后面总会检查到的。

代码这样写:

#include<bits/stdc++.h>
using namespace std;
int minn=0x3f3f3f3f,n,m,ex,ey,vis[101][101],mmap[101][101];
int dis[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
struct place{
	int ax,ay,depth;
};
void bfs(){
	queue<place> q;
	place front;
	front.ax=0,front.ay=0,front.depth=1;
	q.push(front);
	while(!q.empty()){
		front=q.front();
		q.pop();
		if(front.ax==ex&&front.ay==ey){
			minn=front.depth;
			return ;
		}
		for(int i=0;i<4;i++){
			int dx=front.ax+dis[i][0],dy=front.ay+dis[i][1];
			if(dx>=0&&dy>=0&&dx<n&&dy<m&&!vis[dx][dy]&&mmap[dx][dy]){
				vis[dx][dy]=1;
				place xxx;
			    xxx.ax=dx,xxx.ay=dy,xxx.depth=front.depth+1;
				q.push(xxx);
			}
		}
	}
}
int main(){
	cin>>n>>m;
	for(int i=0;i<n;i++)
		for(int j=0;j<m;j++){
			char ch;cin>>ch;
			if(ch=='.') mmap[i][j]=1;
			else mmap[i][j]=0;
		}
	ex=n-1,ey=m-1;
	bfs();
	cout<<minn;
	return 0;
}

这不就AC了!

接着看第三类:

模板题:http://ybt.ssoier.cn:8088/problem_show.php?pid=1255

曾经我走迷宫时(真实迷宫):

迷宫不会走怎办?上帝视角看一看。太过复杂怎么办?想编程序就完蛋。可是我现在会编了!

只要在结构体里加上父节点(上一步)的坐标,然后专门做一个查询父节点的二维数组,专门用来查询那个节点的父节点;

然后再做一个递归输出的函数,就大功告成了!!!

上代码!!!

#include<bits/stdc++.h>
using namespace std;
int vis[6][6],mmap[6][6];
int dis[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
struct place{
	int ax,ay,fx,fy;
}father[6][6],front;
void print(int x,int y){
	if(x==-1&&y==-1) return ;
	print(father[x][y].fx,father[x][y].fy);
	cout<<'('<<x<<", "<<y<<')'<<endl;
}
void bfs(){
	queue<place> q;
	front.ax=0,front.ay=0,front.fx=-1,front.fy=-1;vis[0][0]=1;
	q.push(front);
	while(!q.empty()){
		front=q.front();father[front.ax][front.ay]=front;q.pop();
		for(int i=0;i<4;i++){
			int dx=front.ax+dis[i][0],dy=front.ay+dis[i][1];
			if(dx>=0&&dy>=0&&dx<5&&dy<5&&!vis[dx][dy]&&!mmap[dx][dy]){
				place now;
				vis[dx][dy]=1;
				now.ax=dx,now.ay=dy,now.fx=front.ax,now.fy=front.ay;
				q.push(now);
			}
		}
	}
	print(4,4);
}
int main(){
	for(int i=0;i<5;i++) for(int j=0;j<5;j++) cin>>mmap[i][j];
	bfs();
	return 0;
}

你学费了吗?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值