广度优先搜索bfs

来源:互联网 发布:软件开发项目生命周期 编辑:程序博客网 时间:2024/04/30 16:34

bfs即广度优先搜索算法,其是搜索算法中的一种。

1. dfs常用于寻找是否存在解:

其从A节点出发,选取一个临近点B,然后不断深入,在搜索完B的下属节点(EHIF)后,回到A再搜索临近A的C节点,以此类推。

2. bfs则用于在最短的时间或最少的移动距离内找到解:

其往往从A节点出发,搜索周围所有的围绕节点(BCD),然后再搜索所有围绕节点的临近围绕节点(EFGK),故bfs常常会超内存。


acm中搜索算法常常表现为迷宫搜索。

即在二维数组中告诉你初始坐标和最终目标,让你求最短的到达时间,每单位时间只能移动一格,在迷宫中往往还有障碍或消耗时间的东西。


在解决bfs迷宫问题中,因为其是以初始节点为中心,一层一层的去遍历,所以需要存储节点之间的顺序,让临近层比稍远的层先搜索到。

所以需要用到队列,详见下图:



c++的标准库中提供了队列queue:

1. 引入头文件:

#include<queue>
using namespace std;


2. 队列定义:

queue<数据类型名> 变量名;


3. 队列的有关函数:
empty():判断队列是否为空,当队列为空时返回1
push():  将一个元素置入队列末尾
front():   返回队列的首元素(也就是第一个被置入的元素)
pop():    从队列中删除首元素

用以上这四个便可以做bfs的迷宫题


下面直接引出bfs一般的模板:

#include<stdio.h>#include<string.h>#include<queue>using namespace std;struct place               定义一个结构体,存储坐标和时间{    int x,y,t;             x记录横坐标,y记录纵坐标,t表示从初始位行动至现在位置所消耗的时间}abc,xyz;                  开两个结构体abc,xyz(abc表示旧坐标,xyz表示由旧坐标通过方向数组产生的新坐标)queue<struct place> p;     定义一个struct place型队列int 行数,列数;             全局变量,表示地图大小char map[100][100]         地图,一般大小不超过100*100int vis[100][100]          用于标记该位置是否已走过int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}     方向数组,分别表示向上,向下,向左,向右void bfs()                 进入bfs{    while(!p.empty())      队列为空时跳出,表示未能达到最终目标    {        abc=p.front();     将队首赋给abc        p.pop();           从队列中弹出队首               if()               判断现在abc结构体所指的map[][]是否为最终目标        {            ......         如果是,则跳出,程序运行完成            return;        }        for(i=0;i<4;i++)   循环周围四个方向        {            xyz.x=abc.x+dir[i][0];            xyz.x用于记录由abc.x产生的新的横坐标            xyz.y=abc.y+dir[i][1];            xyz.y用于记录由abc.y产生的新的纵坐标            如果新坐标还在迷宫里且不是障碍物,也没有被走过            if((xyz.x>=1&&xyz.x<=行数)&&(xyz.y>=1&&xyz.y<=列数))&&(!vis[xyz.x][xyz.y])&&(map[xyz.x][xyz.y]!='障碍标记'))            {                xyz.t=abc.t+1;                耗时+1                p.push(xyz);                  将新产生的xyz压入队尾                vis[xyz.x][xyz.y]=1;          标记为走过            }        }    }}int main(){    memset(vis,0,sizeof(vis));               初始化vis全部为0,即地图内任意位置均未被走过    while(~scanf("%d%d",&行数,&列数))         读入地图的行数与列数    {        for(i=1;i<=行数;i++)        {            for(j=1;j<=列数;j++)            {                  scanf("%c",&map[i][j]);     读入地图,xx表示可以走,xx表示障碍标记            }            这里可能需要吃回车        }        abc.x=abc.y=1;                        初始位从(1,1)开始,也可以变为读入初始坐标        abc.t=0;                              在(1,1)时,因为还没开始行动,所以耗时为0        p.push(abc);                          将初始位压入队列        bfs();                                从初始位开始广度优先搜索        while(!p.empty())                     清空队列,否则影响下一组输入            p.pop();    }    return 0;}

当然,如果把队列的定义放入bfs函数内(即queue成为局部变量),这样可能具有更高的效率,因为这样就不用每次都清空队列了。

1 0
原创粉丝点击