c++之广度优先搜索
广度优先搜索BFS(Breadth First Search)也称为宽度优先搜索,它是一种先生成的结点先扩展的策略。
在广度优先搜索算法中,解答树上结点的扩展是按它们在树中的层次进行的。首先生成第一层结点,同时检查目标结点是否在所生成的结点中,如果不在,则将所有的第一层结点逐一扩展,得到第二层结点,并检查第二层结点是否包含目标结点,……,对层次为n+1的任一结点进行扩展之前,必须先考虑层次完层次为n的结点的每种可能的状态。因此,对于同一层结点来说,求解问题的价值是相同的,可以按任意顺序来扩展它们。通常采用的原则是先生成的结点先扩展。
为了便于进行搜索,要设置一个表存储所有的结点。由于在广度优先搜索算法中,要满足先生成的结点先扩展的原则,所以存储结点的表一般采用队列这种数据结构。
在编写程序时,可用数组q模拟队列。front和rear分别表示队头指针和队尾指针,初始时front=rear=0。
元素x入队操作为 q[rear++]=x;
元素x出队操作为 x =q[front++];
广度优先搜索算法的搜索步骤一般是:
(1)从队列头取出一个结点,检查它按照扩展规则是否能够扩展,如果能则产生一个新结点。
(2)检查新生成的结点,看它是否已在队列中存在,如果新结点已经在队列中出现过,就放弃这个结点,然后回到第(1)步。否则,如果新结点未曾在队列中出现过,则将它加入到队列尾。
(3)检查新结点是否目标结点。如果新结点是目标结点,则搜索成功,程序结束;若新结点不是目标结点,则回到第(1)步,再从队列头取出结点进行扩展。
最终可能产生两种结果:找到目标结点,或扩展完所有结点而没有找到目标结点。
如果目标结点存在于解答树的有限层上,广度优先搜索算法一定能保证找到一条通向它的最佳路径,因此广度优先搜索算法特别适用于只需求出最优解的问题。当问题需要给出解的路径,则要保存每个结点的来源,也就是它是从哪一个节点扩展来的。
对于广度优先搜索算法来说,问题不同则状态结点的结构和结点扩展规则是不同的,但搜索的策略是相同的。广度优先搜索算法的框架一般如下:
void BFS()
{
队列初始化;
初始结点入队;
while (队列非空)
{
队头元素出队,赋给current;
while (current 还可以扩展)
{
由结点current扩展出新结点new;
if (new 重复于已有的结点状态) continue;
new结点入队;
if (new结点是目标状态)
{
置flag= true; break;
}
}
}
}
对于不同的问题,用广度优先搜索法的算法基本上都是一样的。但表示问题状态的结点数据结构、新结点是否为目标结点和是否为重复结点的判断等方面则有所不同。对具体的问题需要进行具体分析,这些函数要根据具体问题进行编写。
【例1】黑色方块
有一个宽为W、高为H的矩形平面,用黑色和红色两种颜色的方砖铺满。一个小朋友站在一块黑色方块上开始移动,规定移动方向有上、下、左、右四种,且只能在黑色方块上移动(即不能移到红色方块上)。编写一个程序,计算小朋友从起点出发可到达的所有黑色方砖的块数(包括起点)。
例如,如图1所示的矩形平面中,“#”表示红色砖块,“.”表示黑色砖块,“@”表示小朋友的起点,则小朋友能走到的黑色方砖有28块。
(1)编程思路
采用广度优先搜索法解决这个问题。
用数组q模拟队列操作,front为队头指针,rear为队尾指针,初始时front=rear=0。
入队操作为 q[rear++]=cur;
出队操作为 cur=q[front++]。
程序中定义方砖的位置坐标(x,y)为Node类型,定义数组int
visit[N][N]标记某方砖是否已走过,visit[i][j]=0表示坐标(i,j)处的方砖未走过,visit[i][j]=1表示坐标(i,j)处的方砖已走过。初始时visit数组的所有元素值均为0。
具体算法步骤为:
① 将出发点(startx,starty)入队列q,且置visit[startx][starty]=1,表示该处的方砖已被处理,以后不再重复搜索。
② 将队列q的队头元素出栈,得到一个当前方砖cur,黑色方砖计数(sum++),沿其上、下、左、右四个方向上搜索未走过的黑色方砖,将找到的黑色方砖的坐标入队列q。
③ 重复执行②,直至队列q为空,则求出了所有能走过的黑色方砖数。
(2)源程序
#include <iostream>
using namespace std;
#define N 21
struct Node
{
int x;
int y;
};
int dx[]={-,,,};
int dy[]={,,-,};
char map[N][N];
int visit[N][N];
int bfs(int startx, int starty,int w,int h)
{
Node q[N*N],cur,next; // q为队列
int front,rear; // front为队头指针,rear为队尾指针
int i,x,y,sum;
front=rear=; // 队列q初始化
sum=;
cur.x=startx; cur.y=starty;
visit[startx][starty]=;
q[rear++]=cur; // 初始结点入队
while(rear!=front) // 队列不为空
{
cur=q[front++]; // 队头元素出队
sum++; // 方砖计数
for (i=;i<;i++)
{
x=cur.x+dx[i]; y=cur.y+dy[i];
if(x >= &&
x<h && y>= && y<w && map[x][y]!='#'
&& visit[x][y]==)
{
visit[x][y] = ;
next.x=x; next.y=y; // 由cur扩展出新结点next
q[rear++]=next; // next结点入队
}
}
}
return sum;
}
int main()
{
int i,j,pos_x,pos_y,w,h,sum;
while()
{
cin>>w>>h;
if (w== && h==) break;
for(i=;i<h;i++)
{
for(j=;j<w;j++)
{
cin>>map[i][j];
if (map[i][j]=='@')
{
pos_x = i;
pos_y = j;
}
visit[i][j] = 0;
}
}
sum=bfs(pos_x, pos_y,w,h);
cout<<sum<<endl;
}
return ;
}
c++之广度优先搜索的更多相关文章
- 图的广度优先搜索(BFS)
把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...
- 广度优先搜索(BFS)
定义 维基百科:https://en.wikipedia.org/wiki/Breadth-first_search 给定图G=(V,E)和一个可识别的源结点s,广度优先搜索对图G中的边进行系统性的探 ...
- 总结A*,Dijkstra,广度优先搜索,深度优先搜索的复杂度比较
广度优先搜索(BFS) 1.将头结点放入队列Q中 2.while Q!=空 u出队 遍历u的邻接表中的每个节点v 将v插入队列中 当使用无向图的邻接表时,复杂度为O(V^2) 当使用有向图的邻接表时, ...
- ACM题目————图的广度优先搜索
题目描述 图的广度优先搜索类似于树的按层次遍历,即从某个结点开始,先访问该结点,然后访问该结点的所有邻接点,再依次访问各邻接 点的邻接点.如此进行下去,直到所有的结点都访问为止.在该题中,假定所有的结 ...
- SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...
- HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)
Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- HDU 1241 Oil Deposits DFS(深度优先搜索) 和 BFS(广度优先搜索)
Oil Deposits Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- HDU 1242 Rescue (BFS(广度优先搜索))
Rescue Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
- SDUT2142数据结构实验之图论二:基于邻接表的广度优先搜索遍历
http://acm.sdut.edu.cn/sdutoj/showproblem.php?pid=2142&cid=1186 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜 ...
- 广度优先搜索BFS
广度优先搜索可以形成一个广度优先搜索树 算法时间为O(V+E),两重循环 输入:图g,起点start(int) 需要的数据结构:队列Q.color数组(存放每个顶点的颜色) 算法过程: 1. 预处理: ...
随机推荐
- Presto原理及安装
背景 MapReduce不能满足大数据快速实时adhoc查询计算的性能要求,Facebook2012年开发,2013年开源 是什么 基于内存的并行计算,Facebook推出的分布式SQL交互式查询引擎 ...
- combogrid设置多选,并获取多选的值
1.combogrid设置多选 1.添加该属性 multiple: true, 2.添加该列 {field:'ck',checkbox:true}, 2.获取多选的值 var arr = $(&quo ...
- CentOS 无法加载 ntfs文件系统类型解决办法
问题: CentOS无法加载ntfs 文件系统类型的移动硬盘. 解决办法: 1.下载rpmforge,下载对应的版本.(对应的CentOS版本,并区分32位和64位). 例如: wget http:/ ...
- three.js 数学方法之Vector3
今天郭先生来说一说three.js的Vector3,该类表示的是一个三维向量(3D vector). 一个三维向量表示的是一个有顺序的.三个为一组的数字组合(标记为x.y和z),可被用来表示很多事物, ...
- WebView in ScrollView:View not displayed because it is too large to fit into a software layer
报错信息 W/View: WebView not displayed because it is too large to fit into a software layer (or drawing ...
- LaTeX公式学习
简介 本文公式较多可能有加载较慢. 使用 LaTeX 的主要原因之一是它可以方便地排版公式.我们使用数学模式来排版公式. 公式 插入公式 可以用一对$来启用数学模式. 行中公式可以用如下方法: $数学 ...
- 下载spring的路径的文章,已经试用没问题
文章:https://blog.csdn.net/ethan__xu/article/details/80273249 spring jar下载路径 http://repo.spring.io/rel ...
- 5万字长文:Stream和Lambda表达式最佳实践-附PDF下载
目录 1. Streams简介 1.1 创建Stream 1.2 Streams多线程 1.3 Stream的基本操作 Matching Filtering Mapping FlatMap Reduc ...
- 两种 HTTP 方法:GET 和 POST
区别 GET POST 可见性 数据在 URL 中对所有人都是可见的. post 方式通过body体进行传输,数据不会显示在 URL 中. 安全性 与 POST 相比,GET 的安全性较差,因为所发送 ...
- 给自己挖坑——DateWay
参考文章 官方手册 官方博客 填坑 目录 简介 使用 1. 引入相关依赖 2. 配置 Dataway,并初始化数据表 3. 配置数据源 4. 把数据源设置到 Hasor 容器中 5. 在SprintB ...