宽度优先搜索(BFS)
预备知识
队列
特点:
1、先进先出(FIFO)
2、从队头删除元素
3、在队尾加入元素
常见操作
1)判断队列是否为空
2)查询队列大小
3)访问队首元素
4)访问队尾元素
5)加入元素
6)删除元素
STL中队列的基本用法
1)创建队列对象:queue<元素类型>队列名;
2)队列添加元素:队列名.push(元素名);
3)去掉队首元素:队列名.pop();
4)访问队首元素:队列名.front();
5)访问队尾元素:队列名.back();
6)判断是否为空:队列名.empty();
7)返回队列大小:队列名.size();
现在来看BFS,首先看一个例题。
二叉树的层次遍历。
很显然层次遍历的结果为:5 1 7 2 4 6 3.
那么我们如何通过代码实现呢?
算法思想:
维护一个队列,用于存放结点的信息。当访问到一个结点的时候,先访问该结点,然后将该结点的左右儿子分别入队列。
伪代码:
ccbl(int root)
queue<int>Q;创建一个队列
Q.push(root);将根结点入队列
while(队列不为空){
获得队首元素
将队首元素出队
输出当前结点的值
如果该结点的左儿子不为空,将左儿子加入到队列中
如果该结点的右儿子不为空,将右儿子加入到队列中
}
图的BFS示意图
我们再看一个例题:
题目链接:Problem - 1548 (hdu.edu.cn)
问题描述:
Sample Input
5 1 5
3 3 1 2 5
0
Sample Output
3
解题代码
#include<bits/stdc++.h>
using namespace std;int N,Start,End;
int a[202];
int vis[202]; // 标记数组
struct pos
{int level;int steps;
};
void bfs(); // 函数原型声明int main()
{while(scanf("%d",&N)==1){if(N==0)break;scanf("%d%d",&Start,&End);for(int i=1;i<=N;i++){scanf("%d",&a[i]);vis[i]=0;}bfs();}return 0;
}void bfs()
{pos cur,nex;cur.level=Start;cur.steps=0;queue<pos>qu;qu.push(cur);vis[Start]=1;while(!qu.empty()){cur=qu.front();qu.pop();if(cur.level == End){printf("%d\n",cur.steps);return;}nex.level=cur.level+a[cur.level];nex.steps=cur.steps+1;if(nex.level <= N){if(vis[nex.level]==0){vis[nex.level]=1;qu.push(nex);}}nex.level=cur.level-a[cur.level];nex.steps=cur.steps+1;if(nex.level>=1){if(vis[nex.level]==0){vis[nex.level]=1;qu.push(nex);}}}printf("-1\n");return;
}
运行结果
下面我们再来看一道例题:
题目链接:Problem - 1495 (hdu.edu.cn)
Problem Description
大家一定觉的运动以后喝可乐是一件很惬意的事情,但是seeyou却不这么认为。因为每次当seeyou买了可乐以后,阿牛就要求和seeyou一起分享这一瓶可乐,而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子,它们的容量分别是N 毫升和M 毫升 可乐的体积为S (S<101)毫升 (正好装满一瓶) ,它们三个之间可以相互倒可乐 (都是没有刻度的,且 S==N+M,101>S>0,N>0,M>0) 。聪明的ACMER你们说他们能平分吗?如果能请输出倒可乐的最少的次数,如果不能输出"NO"。
Input
三个整数 : S 可乐的体积 , N 和 M是两个杯子的容量,以"0 0 0"结束。
Output
如果能平分的话请输出最少要倒的次数,否则输出"NO"。
Sample Input
7 4 3
4 1 3
0 0 0
Sample Output
NO
3
Author
seeyou
Source
“2006校园文化活动月”之“校庆杯”大学生程序设计竞赛暨杭州电子科技大学第四届大学生程序设计竞赛
解题代码
#include<iostream>
#include<cstring>
#include<queue>using namespace std;int s,n,m;
int vis[105][105][105];
struct node{int s,n,m;int step;
};bool check(int x,int y,int z){return x == 0 && y == z || y == 0 && x == z || z == 0 && x == y;
}int bfs(){if(s % 2) return 0;queue<node> q;node now,next;now.s = s,now.n = 0,now.m = 0,now.step = 0;q.push(now);vis[s][0][0] = 1;while(q.size()){now = q.front();q.pop();if(check(now.s,now.n,now.m)){return now.step;}// s-->nif(now.s && now.n < n){ // s不为空且n未满 if(now.s < n - now.n){ //s无法倒满n next.n = now.n + now.s;next.s = 0;next.m = now.m;}else{ //s可以倒满 n next.s = now.s - (n - now.n);next.n = n;next.m = now.m;}if(!vis[next.s][next.n][next.m]){next.step = now.step + 1;vis[next.s][next.n][next.m] = 1;q.push(next);}}// s-->mif(now.s && now.m < m){ // s不为空且m未满 if(now.s < m - now.m){ //s无法倒满m next.m = now.m + now.s;next.s = 0;next.n = now.n;}else{ //s可以倒满 m next.s = now.s - (m - now.m);next.m = m;next.n = now.n;}if(!vis[next.s][next.n][next.m]){next.step = now.step + 1;q.push(next);vis[next.s][next.n][next.m] = 1;}}// n-->sif(now.n && now.s < s){ // n不为空且s未满 if(now.n < s - now.s){ //n无法倒满s next.s = now.s + now.n;next.n = 0;next.m = now.m;}else{ //n可以倒满 s next.n = now.n - (s - now.s);next.s = s;next.m = now.m;}if(!vis[next.s][next.n][next.m]){next.step = now.step + 1;q.push(next);vis[next.s][next.n][next.m] = 1;}}// n-->mif(now.n && now.m < m){ // n不为空且m未满 if(now.n < m - now.m){ //n无法倒满m next.m = now.m + now.n;next.n = 0;next.s = now.s;}else{ //n可以倒满 m next.n = now.n - (m - now.m);next.m = m;next.s = now.s;}if(!vis[next.s][next.n][next.m]){next.step = now.step + 1;q.push(next);vis[next.s][next.n][next.m] = 1;}}// m-->sif(now.m && now.s < s){ // m不为空且s未满 if(now.m < s - now.s){ //m无法倒满snext.s = now.s + now.m;next.m = 0;next.n = now.n;}else{ //m可以倒满 s next.m = now.m - (s - now.s);next.s = s;next.n = now.n;}if(!vis[next.s][next.n][next.m]){next.step = now.step + 1;q.push(next);vis[next.s][next.n][next.m] = 1;}}// m-->nif(now.m && now.n < n){ // m不为空且n未满 if(now.m < n - now.n){ //m无法倒满n next.n = now.n + now.m;next.m = 0;next.s = now.s;}else{ //m可以倒满 n next.m = now.m - (n - now.n);next.n = n;next.s = now.s;}if(!vis[next.s][next.n][next.m]){next.step = now.step + 1;q.push(next);vis[next.s][next.n][next.m] = 1;}}}return 0;
}int main()
{while(cin>>s>>n>>m && s && n && m){memset(vis,0,sizeof(vis));int ans = bfs();if(ans == 0)cout<<"NO"<<endl;elsecout<<ans<<endl;}return 0;
}
运行结果
状态转移规则(倒水规则):
如果i水杯内水的容量大于j水杯内倒满所需的容量x,则——i水杯倒水后的容量为:i-x,j水杯倒水后容量为:j+x.
如果i水杯内水的容量小于j水杯内倒满所需的容量x,则——i水杯倒水后的容量为:0,j水杯倒水后容量为:j+x.
每操作一次,最少倒水次数+1.
总结
BFS基本思想:
从初始状态S开始,利用规则,生成所有可能的状态,构成树的下一层结点。
检查是否出现目标状态G,若未出现,就对该层所有状态结点,分别依次利用规则,生成再下一层的所有状态结点。
对新一层的所有状态结点继续检查是否出现G,若未出现,继续按上面思想生成再下一层的所有状态结点,这样一层一层往下展开,直到出现目标状态为止。
BFS算法(伪代码):
Node bfs(node source,node target){
memset(visit,0,sizeof(visit));
queue<node>Q;
Q.push(source);
visit[source]=1;
while(!Q.empty()){
Node a = Q.front();
Q.pop();
if(a==target)
{ return a; }
for(对于a所有的后继结点b)
if(visit[b]){ continue; }
Q.push(b);
visit[b]=1;// 剪枝,保证结点只进队列一次
}
return NULL;
}
宽度优先搜索(BFS)相关推荐
- 广度/宽度优先搜索(BFS)详解
1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名. 一般可以用它做什么呢?一 ...
- 【算法入门】广度/宽度优先搜索(BFS)
广度/宽度优先搜索(BFS) [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/04/27 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述) ...
- (宽度优先搜索)bfs(包含所有模型)
持续更新中(点个赞吧) 首先,我们要了解什么是bfs: 宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型. 其实bfs是盲目的搜索周围,知道搜到目的 ...
- 图/树——宽度优先搜索(BFS)
转载 宽度优先搜索(BFS, Breadth First Search)是一个针对图和树的遍历算法.发明于上世纪50年代末60年代初,最初用于解决迷宫最短路径和网络路由等问题. 对于下面的树而言,BF ...
- 野人与传教士——宽度优先搜索(完整报告,含全部代码)
题目: 野人与传教士渡河问题:3个野人与3个传教士打算乘一条船到对岸去,该船一次最多能运2个人,在任何时候野人人数超过传教士人数,野人就会把传教士吃掉,如何用这条船把所有人安全的送到对岸?在实现基本程 ...
- 深度优先搜索和宽度优先搜索
深度优先搜索和宽度优先搜索 bfs和dfs都是遍历图的方法.dfs是不撞南墙不回头,bfs慢慢来,一层一层来. 类型 空间(h为高度) 时间(h为高度) 采用的数据结构 特点 DFS O(h) O( ...
- 【BFS宽度优先搜索】
一.求所有顶点到s顶点的最小步数 1 //BFS宽度优先搜索 2 #include<iostream> 3 using namespace std; 4 #include<que ...
- 数据结构与算法—图论之dfs、bfs(深度优先搜索、宽度优先搜索)
文章目录 前言 邻接矩阵和邻接表 深度优先搜索(dfs) 宽度(广度)优先搜索(bfs) 总结与比较 前言 在有向图和无向图中,如果节点之间无权值或者权值相等,那么dfs和bfs时常出现在日常算法中. ...
- 层层递进——宽度优先搜索(BFS)
问题引入 我们接着上次"解救小哈"的问题继续探索,不过这次是用宽度优先搜索(BFS). 注:问题来源可以点击这里 http://www.cnblogs.com/OctoptusLi ...
- BFS(宽度优先搜索、广度优先搜索)
宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型.Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想.其别名又 ...
最新文章
- np.random.permutation
- 干掉Postman?测试接口直接生成API文档,这工具强烈推荐!
- 实战3--设计管理模块,整合!!!
- 4/5 MySQL入门总结:数据表(TABLE)操作
- XElement 和 XDocument 到底有什么区别?
- Spring Integration完整示例
- zabbix无效监控项_zabbix4.2zabbix自定义监控项、添加新的监控项
- 【Django 2021年最新版教程30】ubuntu中停止和重启django项目
- ERP-非财务人员的财务培训教(一.二)------财务基础知识
- 英语学习口诀大全be 的用法口诀
- 学习信号量 sem_init、sem_destroy、sem_post、sem_wait、sem_trywait、sem_getvalue
- python画太极图
- 软件工程——(1)软件与软件工程 思维导图
- 【C语言总结】C语言预处理器
- servu ip段访问_高防IP是如何防御DDOS/CC攻击的,防御原理是什么?
- latex参考文献中修改指定作者的格式来突出显示
- 抖音这样拍摄短视频,能让你轻松上热门涨粉丨国仁网络资讯
- 20个VC开发小技巧
- 123457123456#2#----com.MC.ShiZi365--前拼后广--儿童识字Game-mc22222222222222222
- 使用canvas绘制圆环进度条