BFS(一):广度优先搜索的基本思想
广度优先搜索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[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
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=0; // 队列q初始化
sum=0;
cur.x=startx; cur.y=starty;
visit[startx][starty]=1;
q[rear++]=cur; // 初始结点入队
while(rear!=front) // 队列不为空
{
cur=q[front++]; // 队头元素出队
sum++; // 方砖计数
for (i=0;i<4;i++)
{
x=cur.x+dx[i]; y=cur.y+dy[i];
if(x >=0 && x<h && y>=0 && y<w && map[x][y]!='#' && visit[x][y]==0)
{
visit[x][y] = 1;
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(1)
{
cin>>w>>h;
if (w==0 && h==0) break;
for(i=0;i<h;i++)
{
for(j=0;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 0;
}
BFS(一):广度优先搜索的基本思想的更多相关文章
- 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 ...
- HDU 1104 Remainder( BFS(广度优先搜索))
Remainder Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- HDU 4707 Pet(DFS(深度优先搜索)+BFS(广度优先搜索))
Pet Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submissio ...
- HDU 1104 Remainder (BFS(广度优先搜索))
Remainder Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Sub ...
- 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 ...
- 地牢逃脱(BFS(广度优先搜索))
题目描述 给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一 ...
- python调用C++实例:用C++对numpy执行BFS(广度优先搜索)
下文的代码可能展示不全,详情请下载文件:用cpp遍历ndarray.rar 问题背景: 现在我有一张二值图test.npy,需要对其闭区域进行孔洞填充,如下图所示: 文件下载链接:用cpp遍历ndar ...
- 胜利大逃亡,bfs,广度优先搜索
题目描述: Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个A*B*C的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius ...
随机推荐
- 微软输入法TSF SampleIME 代码浅说
原文:微软输入法TSF SampleIME 代码浅说 微软提供了一个简单的TSF拼音输入法的示例SampleIME,主要的问题是:不支持数字键选候选字,不能自动上屏,没有联想功能.在笔者开发动态输入法 ...
- AABB边框、OBB边框、通过比较球包围
1) AABB 包围盒: AABB 包围盒是与坐标轴对齐的包围盒, 简单性好, 紧密性较差(尤其对斜对角方向放置的瘦长形对象, 採用AABB, 将留下非常大的边角空隙, 导致大量不是必需的包围盒相交測 ...
- win7(64bit)使用mingw64配置gtkmm
因为linux命令不熟悉,加上时间不充裕,仍然决定在win7_64bit下开发GUI程序,选择gtkmm是因为: 1. 在图形界面程序中,windows系统当之无愧GUI之王,用户友好性其他OS无法替 ...
- 基于Linux C的socketEthereal程序和Package分析 (一个)
执行测试平台:CentOS 6.5发行版,内核版本号3.11 1. Linux抓包源程序 在OSI七层模型中.网卡工作在物理层和数据链路层的MAC子层. 进行网络通信时.源主机通过socket( ...
- WCF的几个注意事项
wcf托管服务注意的问题 加上项目分为客户端-WCF服务-逻辑层-数据库三层wcf一直出现异常,说没有初始化啊之类的,如果你的逻辑代码确定没有问题的话,思考是不是wcf的配置文件(app.config ...
- jquery trim()的用法
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- VS2012中使用CEGUI项目发布到XP平台的问题(核心方法就一句话。“你项目使用的所有外部依赖库都用/MT编译。”)
接着上一篇文章,详细说说如何把一个带CEGUI的项目发布到XP平台. 这个问题纠缠了我好几天.这里把详细解决思路记下来.有同样问题的朋友可以少走很多弯路. 核心方法就一句话.“你项目使用的所有外部依赖 ...
- c# 全局钩子实现扫码枪获取信息。
原文:c# 全局钩子实现扫码枪获取信息. 1.扫描枪获取数据原理基本相当于键盘数据,获取扫描枪扫描出来的数据,一般分为两种实现方式. a)文本框输入获取焦点,扫描后自动显示在文本框内. b)使用键盘钩 ...
- ASP.NET CORE系列【六】Entity Framework Core 之数据迁移
原文:ASP.NET CORE系列[六]Entity Framework Core 之数据迁移 前言 最近打算用.NET Core写一份简单的后台系统,来练练手 然后又用到了Entity Framew ...
- .NET CORE EnvironmentVariable
.NET CORE System variables SETIn System variablese.g1:Variable name: ASPNETCORE_ENVIRONMENTVariable ...