当前位置: 首页 > news >正文

蓝桥备考--必考题型--广度优先搜索bfs

蓝桥杯近几年基本上都会出一道广度优先搜索题型bfs

广度优先搜索

BFS(广度优先搜索,Breadth-FirstSearch)是一种用于遍历或搜索树或图的算法。它从根节点(或任意节点)开始,逐层访问邻近节点,直到找到目标或遍历完所有节点。

BFS的基本步骤:

  • 1.初始化队列:将起始节点放入队列。
  • 2.访问节点:从队列中取出一个节点并访问。
  • 3.扩展邻近节点:将当前节点的所有未访问邻近节点加入队列。
  • 4.重复:重复步骤2和3,直到队列为空。

BFS的特点: 使用队列:BFS使用队列(FIFO)来管理待访问节点。

逐层遍历:BFS按层扩展,先访问离起始节点最近的节点。

空间复杂度高:在最坏情况下,BFS需要存储所有节点,空间复杂度为O(V),其中V是节点数。

时间复杂度:对于图,时间复杂度为O(V+E),V是节点数,E是边数。

基本做题上都是这个步骤,答案的模版比较固定,就是有一些题会有一些小细节需要注意

下面几道题是由浅入深,逐渐增大难度,建议安装顺序食用,效果比较好!

题目1

迷宫

题意:给定一个n*m的二维整数数组,用来表示一个迷宫,数组中只包含.或#,其中.表示 可以走的路,#表示不可通过的墙壁。 最初,有一个人位于左上角(0,0)处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。 请问,该人从左上角移动至右下角处,至少需要移动多少次。

数据保证(0,0)处和(n-1,m-1)处的数字为0,且一定至少存在一条通路。

输入格式

第一行包含两个整数n和m。

接下来n行,每行包含m(.或#),表示完整的二维数组迷宫。

输出格式

输出一个整数,表示从左上角移动至右下角的最少移动次数。

数据范围

1≤n,m≤100

输入样例:

5 5

. . # # #

# . . . .

# . # . #

# . # . #

# . # . . 

输出样例:

9

代码1

#include<bits/stdc++.h>
using namespace std;

int n,m;
char a[100][100];
struct Point
{
	int x, y, step;
};

queue<Point> q;//队列

bool vis[100][100];//0或1标识

int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };

int bfs()
{
	while (1)
	{
		Point q1 = q.front();
		q.pop();

		for (int i = 0; i < 4;i++)
		{
			int x1 = q1.x + dir[i][0];
			int y1 = q1.y + dir[i][1];
			if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && a[x1][y1] == '.' && vis[x1][y1] == 0)
			{
				if (x1 == n - 1 && y1 == m - 1)
				{
					return q1.step + 1;
				}
				q.push(Point{ x1,y1,q1.step + 1 });
				vis[x1][y1] = 1;
			}
		}
	}
}

int main()
{
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j<m;j++)
		{
			cin >> a[i][j];
		}
	}

	q.push(Point{0,0,1});

	vis[0][0] = 1;

	cout << bfs();

	return 0;
}

题目2

数水坑

题目描述

由于近期的降雨,农民约翰的田地里的许多地方都积水了,用一个N×M(1<=N<=100; 1<=M<=100)的网格图表示。每个网格中有水(“W”)或是旱地(“.”)。一个网格与周围的 八个网格相连,而一组相连的网格视为一个水坑。农夫约翰想知道他的地里形成了多少个水 坑。给出一张农夫约翰的田地图,确定当中有多少个水坑。

输入

第一行:两个空格隔开的整数:N和M 第二行到第N+1行:每行M个字符,每个字符是‘W’或‘.’,它们表示网格图中的一排。字符之间没有空格。

输出

一行:水坑的数量

样例输入

W........WW.

.WWW.....WWW

....WW...WW.

.........WW.

.........W..

..W......W..

.W.W.....WW.

W.W.W.....W.

.W.W......W.

..W.......W.

样例输出

3

这道题注意一下是8个方向移动!

代码2

#include<bits/stdc++.h>
using namespace std;


int n, m;

char a[100][100];
struct Point
{
	int x, y;
};
queue<Point> q;
bool vis[100][100] ;
int dir[8][2] = { {1,0},{0,1},{-1,0},{0,-1},{-1,-1},{1,1},{-1,1},{1,-1} };


void bfs()
{
	while (!q.empty())
	{
		Point q1 = q.front();
		q.pop();
		for (int i = 0; i < 8; i++)
		{
			int x1 = q1.x + dir[i][0];
			int y1 = q1.y + dir[i][1];
			if (x1 >= 0 && x1 < n && y1 >= 0 && y1 < m && a[x1][y1] == 'W' && vis[x1][y1] == 0)
			{
				q.push(Point{ x1,y1 });
				vis[x1][y1] = 1;
			}

		}
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			cin >> a[i][j];
		}
	}

int ans=0;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
		{
			if (a[i][j] == 'W' && vis[i][j] == 0)
			{
				q.push(Point{ i,j });
				vis[i][j] = 1;
				bfs();
				ans++;
			}
			
		}
	}
	 
	cout << ans;

	return 0;
}

题目3

拐弯

题目描述

给出一张地图,这张地图被分为n×m(n,m<=100) 个方块,任何一个方块不是平地就是高山。平地可以通过,高山则不能。现在你处在地图的 (x1,y1)这块平地,问:你至少需要拐几个弯才能到达目的地(x 2,y2)?你只能沿着水平和垂直方向的平地上行进,拐弯次数就等于行进方向的改变(从水平到垂直或从垂直到水平)的次数。

输入

第1行:n∗ m

第2至n+1行:整个地图地形描述(0:空地;1: 高山)

第n +2行:x1y1x2y2(分别为起点、终点坐标)

输出

s(即最少的拐弯次数)

样例输入

5 7

1 0 0 0 0 1 0

0 0 1 0 1 0 0

0 0 0 0 1 0 1

0 1 1 0 0 0 0

0 0 0 0 1 1 0

1 3 1 7

样例输出

5

注意边界!注意是最少!注意第一步走不算拐弯,需要减去!

代码3

#include<bits/stdc++.h>
using namespace std;

int n, m;
int a[100][100];

struct Point
{
	int x, y, lastdir, guai;//坐标、上次拐的方向、拐的次数
};

queue<Point> q;
int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
int vis[100][100] = { 0 };

int x, y, x2, y2;
int min_guai = INT_MAX;

void bfs()
{
	while (!q.empty())
	{
		Point q1 = q.front();
		q.pop();
		for (int i = 0; i < 4; i++)
		{
			int x1 = q1.x + dir[i][0];
			int y1 = q1.y + dir[i][1];

			if (x1 > 0 && x1 <= n && y1 > 0 && y1 <= m && a[x1][y1] != 1 && vis[x1][y1] == 0)
			{
				if (x1 == x2 && y1 == y2)//终点
				{
					if (q1.lastdir != i)//拐弯记录
					{
						q1.guai++;
						q1.lastdir = i;
					}
					min_guai=min(q1.guai,min_guai);
					break;
				}
				else
				{
					if (q1.lastdir != i)//拐弯记录
					{
						q1.guai++;
					}
					q.push(Point{ x1,y1,i,q1.guai });
				}
				vis[x1][y1] = 1;
			}

		}
	}

}

int main()
{
	cin >> n >> m;

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> a[i][j];
		}
	}
	cin >> x >> y >> x2 >> y2;
	Point q0{ x,y,4,0 };
	vis[x][y] = 1;
	q.push(q0);
	bfs();
	cout << min_guai-1 << endl;//起步记录了1次,结果减去

	return 0;
}

少年没有乌托邦,心向远方自明朗!

如果这个博客对你有帮助,给博主一个免费的点赞就是最大的帮助❤
欢迎各位点赞,收藏关注哦❤
如果有疑问或有不同见解,欢迎在评论区留言❤
后续会继续更新大连理工大学相关课程和有关蓝桥杯的内容和示例
点赞加关注,学习不迷路,好,本次的学习就到这里啦!!!

ok,我们下次再见!

 

 

相关文章:

  • 带旋转的目标标注工具-X-AnyLabeling
  • 【pytest框架源码分析五】pytest插件的注册流程
  • 基于Netty实现高性能HTTP服务的架构解析
  • 设备健康管理:给工业设备装上 “智能体检中心”—— 从故障救火到全生命周期守护
  • 基于SpringBoot的“ERP-物资管理”的设计与实现(源码+数据库+文档+PPT)
  • WPF 开发从入门到进阶(五)
  • shell 脚本搭建apache
  • MCP(Model Context Protocol)的介绍与开发初体验
  • Java面试黄金宝典4
  • Clion远程开发配置
  • 【QA】C和C++有哪些常用的调用约定
  • 记录一次,rabbitmq开启stomp插件之后,还是连不上15674端口的问题
  • Baklib企业CMS元数据与协作管理优化
  • Java Spring 中循环依赖的解决之道
  • npm error gyp info
  • AI里的RAG到底是什么?
  • 春天遇到了冬天的吻
  • 《解锁元宇宙构建:AI与云原生区块链的协同奥秘》
  • Web爬虫利器FireCrawl:全方位助力AI训练与高效数据抓取。本地部署方式
  • openEuler24.03 LTS下安装Hive3
  • 国家网信办举办在欧中资企业座谈会,就数据跨境流动等进行交流
  • 深观察丨从“不建议将导师挂名为第一作者”说开去
  • 广东省副省长刘红兵跨省任湖南省委常委、宣传部部长
  • 俄外长:俄将在不损害伙伴关系前提下发展对美关系
  • 何立峰出席驻沪中央金融机构支持上海建设国际金融中心座谈会并讲话
  • 张元济和百日维新