寒假算法学习(BFS)

BFS概念

广度优先搜索,还可称为宽度优先搜索,简称BFS,是一种图算法,用于遍历或搜索图或树的数据结构。它从图的起始节点开始,逐层访问与起始节点相邻的节点,然后逐层扩展,直到找到目标节点或遍历完整个图。在BFS过程中,每一层的节点都会在同一层级上被访问,因此它遍历的是图的广度。

BFS可用于解决下列问题

个人认为:

  1. 从A点出发是否存在到达B的路径;
  2. 从A出发到达B的最短路径:

百度查的:

  1. 最短路径问题: BFS可以用来寻找两个节点之间的最短路径,因为它会优先访问与起始节点相邻的节点,逐层扩展,直到找到目标节点。

  2. 连通性问题: BFS可以检测图中的连通性,即判断两个节点是否相互可达。

  3. 拓扑排序: 如果图是一个有向无环图(DAG),BFS可以用于拓扑排序,确定节点之间的依赖关系顺序。

  4. 迷宫求解: BFS可以用于解决迷宫问题,通过逐层扩展,找到从起始位置到目标位置的路径。

  5. 网络广播: 在计算机网络中,BFS可以用于广播消息或查找网络中的特定节点。

BFS算法的过程:

  1. 选择起始节点: 从图或树的某个节点开始,将其标记为已访问并加入队列。

  2. 遍历相邻节点: 从队列中取出一个节点,访问其所有未被访问过的相邻节点,将它们标记为已访问并加入队列。这确保了按照广度的顺序逐层遍历。

  3. 重复步骤2: 重复以上步骤,直到队列为空。这意味着已经遍历完整个图或树,或者找到了目标节点。

  4. 检查目标节点: 如果目标节点在遍历过程中被找到,算法结束。否则,算法会继续执行,直到队列为空。

BFS使用队列的数据结构来实现。在遍历过程中,节点按照它们被发现的顺序加入队列,并按照队列的先进先出(FIFO)原则进行处理。这确保了每一层的节点都在同一层级上被访问。

需要注意的是,BFS会保证找到的路径是最短路径,因为它按照层级逐步扩展,优先考虑与起始节点相邻的节点。这使得BFS在解决最短路径问题时非常有效。w

为什么需要用对列?

网上找的

例题:

P1746 离开中山路 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述

爱与愁大神买完东西后,打算坐车离开中山路。现在爱与愁大神在 x1​,y1​ 处,车站在 x2​,y2​ 处。现在给出一个 n×n(n≤1000) 的地图,0 表示马路,1 表示店铺(不能从店铺穿过),爱与愁大神只能垂直或水平着在马路上行进。爱与愁大神为了节省时间,他要求最短到达目的地距离(每两个相邻坐标间距离为 1)。你能帮他解决吗?

输入格式

第 1 行包含一个数 n。

第 2 行到第 n+1 行:整个地图描述(0 表示马路,1 表示店铺,注意两个数之间没有空格)。

第 n+2 行:四个数 x1​,y1​,x2​,y2​。

输出格式

只有 1 行,即最短到达目的地距离。

输入输出样例

输入 

3
001
101
100
1 1 3 3

输出 

4
#include<iostream>   //如果记不住这么多的头文件,可以用万能头文件<bits/stdc++.h>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
#define x first  //宏定义first,second为 x,y 使代码变得稍微有条理(个人认为)
#define y second
#define M 1010
typedef pair<int,int> PII;  //存坐标
queue<PII> q;               //定义对列
int n,sx,sy,fx,fy;
int dist[M][M];           //记录起点到某一点的距离,同时也表示从起点到该点需要移动(搜索)几次
char g[M][M];           //形成地图
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};   //四个方向

int bfs(int x1,int y1){
	memset(dist,-1,sizeof(dist));  //全部初始化为 -1
	q.push({x1,y1});   //入队
	dist[x1][y1]=0;    //起点标记为 0

	while(q.size()){  //队列不空,还可以用 !q.empty()表示
		auto t=q.front();   //取出对头
		q.pop();			//弹出对头

		for(int i=0;i<4;i++){
			int a=t.x+dx[i];
			int b=t.y+dy[i];
			
			if(a<1||a>n||b<0||b>n)continue;  //不能超出边界
			if(g[a][b]!='0')continue;		//不是 0(0为马路),则不能行走
			if(dist[a][b]>=0)continue;		//初始值为 -1,如果此处没有走过,则需要大于等于 0

			q.push({a,b});					//符合要求的点,入队
			dist[a][b]=dist[t.x][t.y]+1;	//用前一个位置到起点的距离 +1,算出该点到起点的距离

			if(dist[fx][fy]>0)				//表示已经到了终点,返回起点到终点移动(搜索)的次数,即dist【x2】【y2】
				return dist[fx][fy];
		}
	}
	return -1;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%s",g[i]+1);
	}
	scanf("%d%d%d%d",&sx,&sy,&fx,&fy);
	int res=bfs(sx,sy);
	printf("%d\n",res);
	return 0;
}

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值