ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

广度优先搜索_BFS

2020-06-12 11:42:11  阅读:269  来源: 互联网

标签:优先 进队 13 BFS 瓷砖 出队 邻居 广度 列为


广度优先搜索算法(英语:Breadth-First Search,缩写为BFS),又译作宽度优先搜索,或横向优先搜索,是一种图形搜索算法。简单的说,BFS是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。
BFS是一种盲目搜索法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能地址,彻底地搜索整张图,直到找到结果为止。

实现

  1. 首先将根节点放入队列中。
  2. 从队列中取出第一个节点,并检验它是否为目标。
    * 如果找到目标,则结束搜索并回传结果。
    * 否则将它所有尚未检验过的直接子节点加入队列中。
  3. 若队列为空,表示整张图都检查过了——亦即图中没有欲搜索的目标。结束搜索并回传“找不到目标”。
  4. 重复步骤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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有