广度优先搜索_BFS
作者:互联网
广度优先搜索算法(英语:Breadth-First Search,缩写为BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。
BFS是一种盲目搜索法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能地址,彻底地搜索整张图,直到找到结果为止。
实现
- 首先将根节点放入队列中。
- 从队列中取出第一个节点,并检验它是否为目标。
* 如果找到目标,则结束搜索并回传结果。
* 否则将它所有尚未检验过的直接子节点加入队列中。 - 若队列为空,表示整张图都检查过了——亦即图中没有欲搜索的目标。结束搜索并回传“找不到目标”。
- 重复步骤2。.
动态演示
详细解释
这里以hdu 1312题为例
hdu 1312 "Red and Black" 有一个长方形的房间,铺着方形瓷砖,瓷砖为红色或黑色。一个人站在黑色瓷砖上,他可以按上、下、左、右方向移动到相邻的瓷砖。但他不能在红色瓷砖上移动,只能在黑色瓷砖上移动。编程计算他可以到达的黑色瓷砖的数量。输入:多组数据,第 1 行包含两个正整数 W 和 H ,W 和 H 分别表示 x 方向和 y 方向上的瓷砖数量。 W 和 H 均不超过 20 ,W 和 H 为 0 时表示输入结束。下面有 H 行,每行包含 W 个字符。每个字符表示一片瓷砖的颜色。用符号表示如下:“ . ” 表示黑色瓷砖;“ # ”表示红色瓷砖;“ @ ” 表示黑色瓷砖上的人,在数据集中只出现一次。
输出:一个数字,这个人从初始瓷砖能到达的瓷砖的总数量(包括起点)
- 要遍历所有可能的点,可以这样走:从起点1出发,走到它所有的邻居2、3;逐一处理每个邻居,例如在邻居2上,再走它的所有邻居4、5、6,重复上述过程,直到所有点都被走到,如下图所示。这是一个扩散的过程
- 如果把搜索空间看作一个池塘,丢一颗石头到起点位置,激起的波浪会一层一层地扩散到整个空间。需要注意的是,扩散按从近到远的顺序进行,因此,从每个被扩散的点到起点的路径都是最短的(前提是各边长度相等,若图为加权图,则不一定是最优解)。这个特征对解决迷宫这样的最短路径问题很有用。
- 用队列来处理这个扩散过程非常清晰、易懂。事实上,甚至可以说 “BFS=队列”
- c++提供了队列这个数据结构,头文件为 queue , 使用起来非常简单方便。
- 1 进队。当前队列是 { 1 }
- 1 出队,1 的邻居 2、3 进队。当前队列为 { 2,3 } (可以理解为从1扩散到2、3)
- 2出队,2的邻居4、5、6进队。当前队列是 {3,4,5,6} (可以理解为从2扩散到4、5、6)
- 3出队,7、8进队,当前队列为 {4,5,6,7,8}
- 4出队,9进队,当前队列为{5,6,7,8,9}
- 5出队,10进队,当前队列为{6,7,8,9,10}
- 6出队,11进队,当前队列为{7,8,9,10,11}
- 7出队,12、13进队,当前队列为{8,9,10,11,12,13}
- 8出队,无邻居进队,当前队列为{9,10,11,12,13}
- 9出队,无邻居进队,当前队列为{10,11,12,13}
- 10出队,14进队,当前队列为{11,12,13,14}
- 11出队,15进队,当前队列为{12,13,14,15}
- 12出队,无邻居进队,当前队列为{13,14,15}
- 13出队,无邻居进队,当前队列为{14,15}
- 14出队,无邻居进队,当前队列为{15}
- 15出队,无邻居进队,当前队列为{} ,队列为空,程序执行结束,返回结果为15
上述过程说明了整个搜索过程,下面用代码来实现:
#include <iostream>
#include <queue>
using namespace std;
char room[23][23];
int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};//四个方向,左上右下
int W,H,ans;
//判断当前坐标是否在房间内
bool check(int x,int y){ return (x>=1 && x<=W && y>=1 && y<=H); }
//存储点的坐标
struct node{ int x,y; };
void BFS(int dx,int dy){
ans = 1; //起点也包含在瓷砖内
queue<node> q;
node start,nexted;
start.x = dx;
start.y = dy;
q.push(start);//第一步的 1 进队
while(!q.empty()){//若队列q已经为空,说明已经搜索完毕
start = q.front();
q.pop();
for(int i=0;i<4;i++){//遍历当前位置的邻居
nexted.x = start.x + dir[i][0];
nexted.y = start.y + dir[i][1];
if(check(nexted.x,nexted.y) && room[nexted.x][nexted.y]=='.'){
room[nexted.x][nexted.y] = '#'; //进队后标记为已处理
ans++;
q.push(nexted);
}
}
}
}
int main()
{
int x,y,dx(0),dy(0);
while(cin>>W>>H){
if(W==0 && H==0)
break;
for(y=1;y<=H;y++){
for(x=1;x<=W;x++){
cin>>room[x][y];
if(room[x][y] == '@'){
dx = x;
dy = y;
}
}
}
ans = 0;
BFS(dx,dy);
cout<<ans<<endl;
}
return 0;
}
参考文献:
算法竞赛-从入门到进阶(罗永军,郭卫斌著)
标签:优先,进队,13,BFS,瓷砖,出队,邻居,广度,列为 来源: https://blog.csdn.net/weixin_45826022/article/details/106385561