基础BFS学习笔记

同步发表于cnblog

B F S \tt BFS BFS 的定义与思想

B F S \tt BFS BFS,学名 B r e a d t h   F i r s t   S e a r c h \mathtt{Breadth\ First\ Search} Breadth First Search,中文名“广度优先搜索”,是一类研究最短路径的算法。

一旦你看到一个题目是求到一个点的最短路径,那么它大概率是 B F S \tt BFS BFS

当我们投一个石子时,水上的涟漪就会一圈一圈的扩散开

而广度优先搜索正是如此实现的:

他像一层波浪,一次搜索“一层”的内容,然后检查每一层中有没有答案,如果有,那么就输出步数。

B F S \tt BFS BFS 算法思想与实现

算法思想

从起点 ( s x , s y ) (sx,sy) (sx,sy) 开始,每次搜一层,如果当前能走且没有走过,那么就到达这一点,更新位置,步数加一。

接下来就是代码实现:

基本定义

  1. B F S \tt BFS BFS 不能重复走,需要一个标记数组 v i s \tt vis vis
  2. 一次可以往 4 4 4 个方向走,要两个方向数组,处理 x x x 轴和 y y y 轴。
  3. 定义一个结构体 n o d e \tt node node,带三个参数 x , y , s t e p x,y,step x,y,step,表示当前在 ( x , y ) (x,y) (x,y),走了 s t e p step step 步。
  4. 每次 B F S \tt BFS BFS 都要一个队列,记录当前走的点,走到了就弹出。
  5. 每次都要记录 n x , n y nx,ny nx,ny,表示走到 ( n x , n y ) (nx,ny) (nx,ny)

代码实现

初始化:

  • 我们现将当前表记走没走过的 v i s vis vis 数组清零,防止数据覆盖
  • 定义一个 n o d e node node 类型 c u r cur cur 为当前的起点,将当前的起点 ( s x , s y ) (sx,sy) (sx,sy) 标记到数组 v i s vis vis 里。
  • c u r cur cur 入队。

开始搜索:

  • 进行 while 循环,条件式 q.empty()==0(当前“一层”还没走完)
  • c u r cur cur 为当前的点(cur=q.front()),弹出当前元素,因为已经走到。
  • 检查,如果当前已经走到终点,那么就直接返回当前元素 c u r cur cur 的步数 s t e p step step
  • 开始 f o r \tt for for 循环,走到 4 4 4 个方向,注意边界条件,不能越界,不是障碍物,不能走过。

下面以这个题为例:
一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。
下面附上代码:

#include <bits/stdc++.h>
using namespace std;
int r, c;
bool vis[1005][1005];
int dx[] = {0, 0, -1, 1};
int dy[] = {-1, 1, 0, 0};
char a[1005][1005];
struct node {
	int x, y, step;
};
int bfs(int sx, int sy)
{
	memset(vis, 0, sizeof(vis));
	queue<node> q;
	node cur = {sx, sy, 1};
	vis[sx][sy] = true;
	q.push(cur);
	while(!q.empty())
	{
		cur = q.front();
		q.pop();
		if (cur.x == r && cur.y == c)
		{
			return cur.step;
		}
		for(int i = 0; i < 4; i++)
		{
			int nx = dx[i] + cur.x;
			int ny = dy[i] + cur.y;
			if (nx > 0 && nx <= r && ny > 0 && ny <= c && vis[nx][ny] == false && a[nx][ny] != '#')
			{
				node nxt = {nx, ny, cur.step + 1};
				q.push(nxt);
				vis[nx][ny] = true;
			}
		}
	} 
	return -1;
 } 
int main()
{
	cin >> r >> c;
	for (int i = 1 ; i <= r; i++)
	{
		for (int j = 1; j <= c; j++)
		{
			cin >> a[i][j];
		}
	}
	cout << bfs(1, 1);
	return 0;
 } 

代码中的基本都在上面讲解了,不会的请私信。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值