广度优先搜索——概念
广搜又叫宽度优先搜索,它是一种与深搜完全不同的搜索策略, 它是从源点出发,逐层搜索出所有的点。
例如:遍历左图中的所有节点
深度优先搜索的遍历输出为: 1-2-5-6-8-3-4-7
广度优先搜索的遍历输出为: 1-2-3-4-5-6-7-8
宽搜一般用在求最少多少步的情况,由于它的逐层特性, 它能保证搜到最小或最少的解。
广度优先搜索——算法框架(重点)
在广搜中我们需要用到队列的知识,因此我们先了解一下队列
队列基本原理入下图
再来了解一下队列的基本操作
·empty() 判断queue容器是否为空
·size() 返回当前queue容器的大小(既有多少元数据)
·front() 访问queue容器的第一个(首部)元素
·back() 访问queue容器的(尾部)最后一个元数据
·push() 向queue容器中插入新的元数据
·emplace() 构造并插入元数据 ·pop() 删除队首数据 ·
swap() 交互两个queue容器的内容
了解了队列,我们就可以学习广搜代码了
void bfs(){
初始化,初始状态入队列q表;
while(!q.empty())
{
for(i=1;i<=max;i++) max为产生子结点的规则数
{ 根据规则数产生子结点;
if(子结点符合条件&&未访问)
{
q.push(子结点);
}新结点放在队尾
if(新结点是目标结点)输出并退出;
}
新结点=q.front();q.pop();始终从头开始搜索
}
}
广搜经典例题
1.细胞
【问题描述】一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下 左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。
如输入阵列
4 10
0234500067
1034560500
2045600671
0000000089
输出
4
【输入】 第一行为矩阵的行n和列m; 下面为一个n×m的矩阵。
【输出】 细胞个数。
【算法分析】
① 读入M*N 矩阵阵列,并将其转化成bool值存入bz[]数组中;
② 沿bz数组矩阵从上到下,从左到右,找到遇到的第一个细胞;
③ 细胞位置入队列h,并沿其上下左右四个方向的细胞位置入队,入队后的bz数组设为false;
④ 将h队的队头出队,并沿其上下左右四个方向的细胞位置入队,入队后的bz数组设为false;
⑤ 重复4,直到h队为空;
⑥ 重复2,直到矩阵无细胞;
⑦ 输出找到的细胞数;
【代码实现】
void bfs(int x,int y){
tmp.x=x;tmp.y=y;// tmp为结构体代表(x,y)
q.push(tmp);
while(!q.empty()){
tmp=q.front(); q.pop();//顶结点出队
int xx=tmp.x, yy=tmp.y;
if(xx<1 || xx>m || yy<1 || yy>n) continue;
if(a[xx][yy]==0 || b[xx][yy]==1) continue;
b[xx][yy]=1;// 访问过的结点标记
for(int i=0;i<4;i++){
tmp.x=xx+dx[i];tmp.y=yy+dy[i];
q.push(tmp);
}
}
}
2.走迷宫
【问题描述】一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可 以走。给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在 水平方向或垂直方向走,不能斜着走。
【输入】 第一行是两个整数,R和C,代表迷宫的长和宽。( 1≤ R,C ≤ 40) 接下来是R行,每行C个字符,代表整个迷宫。 空地格子用‘.’表示,有障碍物的格子用‘#’表示。 迷宫左上角和右下角都是‘.’。
【输出】 输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括 起点和终点。
样例输入
5 5 ..### #.... #.#.# #.#.# #.#..
样例输出
9
【问题分析】
本题求解最少步数,其过程实际为从起点,根据移动规则广搜每一点, 直到到达终点。则需要解决一下问题:
① 构建数据结构并初始化;
② 建立移动规则;
③ 将起点(1,1)放入队首,将其前趋设置为0;
④ 从队首结点出发出发根据移动规则构搜索到能到达的所有子节点;
⑤ 如果 该子节点 符合选取规则 则记录该点的前趋点,同时该点入队列;
⑥ 重复2步,直到到达终点或者超出边界;
【代码实现】
void bfs(int x,int y){
q.push((zb){1,1,1});
while(!q.empty()){
zb t=q.front();
q.pop();
for(int i=0;i<4;i++){
int xx=t.x+dx[i];
int yy=t.y+dy[i];
if(xx==n&&yy==m){
cout<<t.bs+1;
return;
}
if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&a[xx][yy]=='.'&&book[xx][yy]==0){
book[xx][yy]=1;
q.push((zb){xx,yy,t.bs+1});
}
}
}
}
广搜就到这里
记得多做题
端午节安康!!!