广度优先搜索课件

上传人:无*** 文档编号:241310556 上传时间:2024-06-17 格式:PPT 页数:27 大小:322.90KB
返回 下载 相关 举报
广度优先搜索课件_第1页
第1页 / 共27页
广度优先搜索课件_第2页
第2页 / 共27页
广度优先搜索课件_第3页
第3页 / 共27页
点击查看更多>>
资源描述
第八章第八章 广度优先搜索广度优先搜索第八章 广度优先搜索w广度优先搜索的过程广度优先搜索的过程 广度优先搜索算法(又称宽度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。广度优先算法的核心思想是:从初始节点开始,应用算符生成第一层节点,检查目标节点是否在这些后继节点中,若没有,再用产生式规则将所有第一层的节点逐一扩展,得到第二层节点,并逐一检查第二层节点中是否包含目标节点。若没有,再用算符逐一扩展第二层的所有节点,如此依次扩展,检查下去,直到发现目标节点为止。即 从图中的某一顶点V0开始,先访问V0;访问所有与V0相邻接的顶点V1,V2,.,Vt;依次访问与V1,V2,.,Vt相邻接的所有未曾访问过的顶点;循此以往,直至所有的顶点都被访问过为止。这种搜索的次序体现沿层次向横向扩展的趋势,所以称之为广度优先搜索。广度优先搜索的过程 广度优先搜索算法(又称宽w广度优先搜索算法描述:广度优先搜索算法描述:int bfs()初始化,初始状态存入队列;队列首指针head=0;尾指针tail=1;do 指针head后移一位,指向待扩展结点;for(int i=1;i=max;+i)/max为产生子结点的规则数 if(子结点符合条件)tail指针增1,把新结点存入列尾;if(新结点与原已产生结点重复)删去该结点(取消入队,tail减1);else if(新结点是目标结点)输出并退出;while(headtail);/队列为空广度优先搜索算法描述:int bfs()w广度优先搜索注意事项:广度优先搜索注意事项:1、每生成一个子结点,就要提供指向它们父亲结点的指针。当解出现时候,通过逆向跟踪,找到从根结点到目标结点的一条路径。当然不要求输出路径,就没必要记父亲。2、生成的结点要与前面所有已经产生结点比较,以免出现重复结点,浪费时间和空间,还有可能陷入死循环。3、如果目标结点的深度与“费用”(如:路径长度)成正比,那么,找到的第一个解即为最优解,这时,搜索速度比深度搜索要快些,在求最优解时往往采用广度优先搜索;如果结点的“费用”不与深度成正比时,第一次找到的解不一定是最优解。4、广度优先搜索的效率还有赖于目标结点所在位置情况,如果目标结点深度处于较深层时,需搜索的结点数基本上以指数增长。下面我们看看怎样用宽度优先搜索来解决八数码问题。例如图8-1给出广度优先搜索应用于八数码难题时所生成的搜索树。搜索树上的所有结点都标记它们所对应的状态,每个结点旁边的数字表示结点扩展的顺序。粗线条路径表明求得的一个解。从图中可以看出,扩展第个结点,总共生成个结点之后,才求得这个解。此外,直接观察此图表明,不存在有更短走步序列的解。广度优先搜索注意事项:1、每生成一个子结点,广度优先搜索课件【例例8.1】图8-2表示的是从城市A到城市H的交通图。从图中可以看出,从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。图8-2【例8.1】图8-2表示的是从城市A到城市H的交通图。从图中【算法分析算法分析】看到这图很容易想到用邻接距阵来表示,0表示能走,1表示不能走。如图。首先想到的是用队列的思想。a数组是存储扩展结点的队列,ai记录经过的城市,bi记录前趋城市,这样就可以倒推出最短线路。具体过程如下:(1)将城市A入队,队首为0、队尾为1。(2)将队首所指的城市所有可直通的城市入队(如果这个城市在队列中出现过就不入队,可用一布尔数组si来判断),将入队城市的前趋城市保存在bi中。然后将队首加1,得到新的队首城市。重复以上步骤,直到搜到城市H时,搜索结束。利用bi可倒推出最少城市线路。【算法分析】首先想到的是用队列的思想。a数组是w【参考程序参考程序】w#includew#includewusing namespace std;wint ju99=0,0,0,0,0,0,0,0,0,w 0,1,0,0,0,1,0,1,1,w 0,0,1,1,1,1,0,1,1,w 0,0,1,1,0,0,1,1,1,w 0,0,1,0,1,1,1,0,1,w 0,1,1,0,1,1,1,0,0,w 0,0,0,1,1,1,1,1,0,w 0,1,1,1,0,0,1,1,0,w 0,1,1,1,1,0,0,0,1;wint a101,b101;wbool s9;/初始化wint out(int d)/输出过程ww coutchar(ad+64);w while(bd)w w d=bd;w cout-char(ad+64);w w coutendl;w【参考程序】wvoid doit()ww int head,tail,i;w head=0;tail=1;/队首为0、队尾为1w a1=1;/记录经过的城市w b1=0;/记录前趋城市w s1=1;/表示该城市已经到过w do /步骤2w w head+;/队首加一,出队w for(i=1;i=8;i+)/搜索可直通的城市w if(juaheadi=0)&(si=0)/判断城市是否走过w w tail+;/队尾加一,入队w atail=i;w btail=head;w si=1;w if(i=8)w w out(tail);head=tail;break;/第一次搜到H城市时路线最短w w w while(headtail);wwint main()/主程序ww memset(s,false,sizeof(s);w doit();/进行Bfs操作w return 0;wvoid doit()【例例8.2】一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数。如:阵列 4 100234500067103456050020456006710000000089有4个细胞。【算法分析算法分析】从文件中读入m*n矩阵阵列,将其转换为boolean矩阵存入bz数组中;沿bz数组矩阵从上到下,从左到右,找到遇到的第一个细胞;将细胞的位置入队h,并沿其上、下、左、右四个方向上的细胞位置入队,入队后的位置bz数组置为flase;将h队的队头出队,沿其上、下、左、右四个方向上的细胞位置入队,入队后的位置bz数组置为flase;重复4,直至h队空为止,则此时找出了一个细胞;重复2,直至矩阵找不到细胞;输出找到的细胞数。【例8.2】一矩形阵列由数字0到9组成,数字1到9代表细胞,w【参考程序参考程序】w#includewusing namespace std;wint dx4=-1,0,1,0,w dy4=0,1,0,-1;wint bz100100,num=0,n,m;wvoid doit(int p,int q)ww int x,y,t,w,i;w int h10002;w num+;bzpq=0;w t=0;w=1;h11=p;h12=q;/遇到的第一个细胞入队w dow w t+;/队头指针加1w for(i=0;i=0)&(x=0)&(yn)&(bzxy)/判断该点是否可以入队w w w+;w hw1=x;w hw2=y;w bzxy=0;w /本方向搜索到细胞就入队w w while(tw);/直至队空为止w【参考程序】wint main()ww int i,j;w char s100,ch;w scanf(%d%dn,&m,&n);w for(i=0;i=m-1;i+)w for(j=0;j=n-1;j+)w bzij=1;/初始化w for(i=0;i=m-1;i+)w w gets(s);w for(j=0;j=n-1;j+)w if(sj=0)bzij=0;w w for(i=0;i=m-1;i+)w for(j=0;j=n-1;j+)w if(bzij)w doit(i,j);/在矩阵中寻找细胞w printf(NUMBER of cells=%d,num);w return 0;wint main()【例例8.3】最短路径(1995年高中组第4 题)如下图所示,从入口(1)到出口(17)的可行路线图中,数字标号表示关卡。现将上面的路线图,按记录结构存储如下图6:请设计一种能从存储数据中求出从入口到出口经过最少关卡路径的算法。【例8.3】最短路径(1995年高中组第4 题)现将上面的路【算法分析算法分析】该题是一个路径搜索问题,根据图示,从入口(1)到出口(17)可能有多条途径,其中最短的路径只有一条,那么如何找最短路径呢?根据题意,用数组no存储各关卡号,用数组per存储访问到某关卡号的前趋关卡号。其实本题是一个典型的图的遍历问题,我们可以采用图的广度优先遍历,并利用队列的方式存储顶点之间的联系。从入口(1)开始先把它入队,然后把(1)的所有关联顶点都入队,即访问一个顶点,将其后继顶点入队,并存储它的前趋顶点,直到访问到出口(17)。最后,再从出口的关卡号(17)开始回访它的前趋关卡号,直到入口的关卡号(1),则回访的搜索路径便是最短路径。从列表中可以看出出口关卡号(17)的被访问路径最短的是:(17)(16)(19)(18)(1)由此,我们得到广度优先遍历求最短路径的基本方法如下:假设用邻接矩阵存放路线图(aij=1表示I与j连通,aij=0表示i与j不连通)。再设一个队列和一个表示拓展到哪个顶点的指针变量pos。(1)从入口开始,先把(1)入队,并且根据邻接矩阵,把(1)的后继顶点全部入队,并存储这些后继顶点的前趋顶点为(1);再把pos后移一个,继续拓展它,将其后继顶点入队,并存储它们的前趋顶点,直到拓展到出口(目的地(17);【算法分析】注意后继顶点入队前,必须要检查这个顶点是否已在队列中,如果已经在了就不要入队了;这一步可称为图的遍历或拓展;(2)从队列的最后一个关卡号(出口(17)开始,依次回访它的前驱顶点,倒推所得到的路径即为最短路径。主要是依据每个顶点的前趋顶点倒推得到的。实现如下:i=1;while(noi!=17)+i;do cout(noi);cout;i=prei;while(I!=0);【参考程序】留给同学们完成,文件名ex8_3.cpp。注意后继顶点入队前,必须要检查这个顶点是否已【例例8.4】迷宫问题迷宫问题 如下图所示,给出一个N*M的迷宫图和一个入口、一个出口。编一个程序,打印一条从迷宫入口到出口的路径。这里黑色方块的单元表示走不通(用-1表示),白色方块的单元表示可以走(用0表示)。只能往上、下、左、右四个方向走。如果无路则输出“no way.”。入口0-1000000-10000-1000-1-100000-1-1-100-1-100000 出口0000000-1-1【算法分析算法分析】只要输出一条路径即可,所以是一个经典的回溯算法问题,本例给出了回溯(深搜)程序和广搜程序。实现见参考程序。【例8.4】迷宫问题入口0-1000000-10000-1w【深搜参考程序深搜参考程序】w#include wusing namespace std;wint n,m,desx,desy,soux,souy,totstep,a51,b51,map5151;wbool f;wint move(int x,int y,int step)ww mapxy=step;/走一步,作标记,把步数记下来w astep=x;bstep=y;/记路径w if(x=desx)&(y=desy)w w f=1;w totstep=step;w w elsew w if(y!=m)&(mapxy+1=0)move(x,y+1,step+1);/向右w if(!f)&(x!=n)&(mapx+1y=0)move(x+1,y,step+1);/往下w if(!f)&(y!=1)&(mapxy-1=0)move(x,y-1,step+1);/往左w if(!f)&(x!=1)&(mapx-1y=0)move(x-1,y,step+1);/往上w w【深搜参考程序】int main()int i,j;cinnm;/n行m列的迷宫 for(i=1;i=n;i+)/读入迷宫,0表示通,-1表示不通 for(j=1;jmapij;coutsouxsouy;/入口 coutdesxdesy;/出口 f=0;/f=0表示无解;f=1表示找到了一个解 move(soux,souy,1);if(f)for(i=1;i=totstep;i+)/输出直迷宫的路径 coutai,biendl;else coutno way.endl;return 0;int main()【广搜参考程序广搜参考程序】#include using namespace std;int u5=0,0,1,0,-1,w5=0,1,0,-1,0;int n,m,i,j,desx,desy,soux,souy,head,tail,x,y,a51,b51,pre51,map5151;bool f;int print(int d)if(pred!=0)print(pred);/递归输出路径递归输出路径 coutad,bdnm;/n行行m列的迷宫列的迷宫 for(i=1;i=n;i+)/读入迷宫,读入迷宫,0表示通,表示通,-1表示不通表示不通 for(j=1;jmapij;coutsouxsouy;/入口入口 coutdesxdesy;/出口出口 head=0;tail=1;【广搜参考程序】f=0;mapsouxsouy=-1;atail=soux;btail=souy;pretail=0;while(head!=tail)/队列不为空队列不为空 head+;for(i=1;i0)&(x0)&(y=m)&(mapxy=0)/本方向上可以走本方向上可以走 tail+;atail=x;btail=y;pretail=head;mapxy=-1;if(x=desx)&(y=desy)/扩展出的结点为目标结点扩展出的结点为目标结点 f=1;print(tail);break;if(f)break;if(!f)coutno way.endl;return 0;f=0;输入输入1 1:输出输出1 1:输入输入2 2:输出输出2 2:8 58 5-1 -1-1 -1-1-1 -1-1 -1-1 0 0 0 0 -1 0 0 0 0 -1-1 -1-1 0 -1-1 -1-1 0 -1-1 0 0 0 -1-1 0 0 0 -1-1 0 0 -1-1-1 0 0 -1-1-1 0 0 0 -1-1 0 0 0 -1-1 -1-1 0 -1-1 -1-1 0 -1-1 0 0 0 -1-1 0 0 0 -12 12 18 48 42,12,12,22,22,32,32,42,43,44,44,35,36,38 58 5-1 -1-1-1-1-1 -1-1-1-1 0 0 0 0-1 0 0 0 0-1-1 -1-1 0-1-1 -1-1 0-1-1 0 0 0-1-1 0 0 0-1-1 0 0-1-1-1 0 0-1-1-1 0 0 0-1-1 0 0 0-1-1 -1-1-1-1-1 -1-1-1-1-1 0 0 0-1-1 0 0 0-12 12 18 48 4no way.no way.输入1:输出1:输入2:输出2:8 52,18 5no w【上机练习上机练习】1、面积(、面积(area)编程计算由“*”号围成的下列图形的面积。面积计算方法是统计*号所围成的闭合曲线中水平线和垂直线交点的数目。如下图所示,在10*10的二维数组中,有“*”围住了15个点,因此面积为15。0 0 0 0 0 0 0 0 0 00 0 0 0 *0 0 00 0 0 0 *0 0 *0 00 0 0 0 0 *0 0 *00 0 *0 0 0 *0 *00 *0 *0 *0 0 *00 *0 0 *0 *00 0 *0 0 0 0 *0 00 0 0 *0 00 0 0 0 0 0 0 0 0 0【样例输入样例输入】area.in0 0 0 0 0 0 0 0 0 00 0 0 0 1 1 1 0 0 00 0 0 0 1 0 0 1 0 00 0 0 0 0 1 0 0 1 00 0 1 0 0 0 1 0 1 00 1 0 1 0 1 0 0 1 00 1 0 0 1 1 0 1 1 00 0 1 0 0 0 0 1 0 00 0 0 1 1 1 1 1 0 00 0 0 0 0 0 0 0 0 0【样例输出样例输出】area.out 15【上机练习】1、面积(area)【样例输入】area.in【2、营救、营救【问题描述问题描述】铁塔尼号遇险了!他发出了求救信号。距离最近的哥伦比亚号收到了讯息,时间就是生命,必须尽快赶到那里。通过侦测,哥伦比亚号获取了一张海洋图。这张图将海洋部分分化成n*n个比较小的单位,其中用1标明的是陆地,用0标明是海洋。船只能从一个格子,移到相邻的四个格子。为了尽快赶到出事地点,哥伦比亚号最少需要走多远的距离。【输入格式输入格式】第一行为n,下面是一个n*n的0、1矩阵,表示海洋地图最后一行为四个小于n的整数,分别表示哥伦比亚号和铁塔尼号的位置。【输出格式】哥伦比亚号到铁塔尼号的最短距离,答案精确到整数。【输入样例输入样例】save.in30011011001 1 3 3【数据范围数据范围】N=1000【输出样例输出样例】save.out42、营救【输出样例】save.out3、最少转弯问题(、最少转弯问题(TURN)【问题描述问题描述】给出一张地图,这张地图被分为nm(n,m=100)个方块,任何一个方块不是平地就是高山。平地可以通过,高山则不能。现在你处在地图的(x1,y1)这块平地,问:你至少需要拐几个弯才能到达目的地(x2,y2)?你只能沿着水平和垂直方向的平地上行进,拐弯次数就等于行进方向的改变(从水平到垂直或从垂直到水平)的次数。例如:如图,最少的拐弯次数为5。3、最少转弯问题(TURN)【输入格式】第1行:n m第2至n+1行:整个地图地形描述(0:空地;1:高山),如(图)第2行地形描述为:1 0 0 0 0 1 0 第3行地形描述为:0 0 1 0 1 0 0 第n+2行:x1 y1 x2 y2 (分别为起点、终点坐标)【输出格式】s(即最少的拐弯次数)【输入输出样例】(见图):TURN.INTURN.OUT5 71 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 1 1 01 3 1 75【输入格式】TURN.INTURN.OUT5 754.麻将游戏【题目描述】在一种麻将游戏中,游戏是在一个有WH格子的矩形平板上进行的。每个格子可以放置一个麻将牌,也可以不放(如图所示)。玩家的目标是将平板上的所有可通过一条路径相连的两张相同的麻将牌,从平板上移去。最后如果能将所有牌移出平板,则算过关。这个游戏中的一个关键问题是:两张牌之间是否可以被一条路径所连接,该路径满足以下两个特性:1.它由若干条线段组成,每条线段要么是水平方向,要么是垂直方向。2.这条路径不能横穿任何一个麻将牌(但允许路径暂时离开平板)。这是一个例子:在(1,3)的牌和在(4,4)的牌可以被连接。(2,3)和(3,4)不能被连接。你的任务是编一个程序,检测两张牌是否能被一条符合以上规定的路径所连接。4.麻将游戏【输入】第一行有两个整数w,h(1=w,h=75),表示平板的宽和高。接下来h行描述平板信息,每行包含w个字符,如果某格子有一张牌,则这个格子上有个X,否则是一个空格。平板上最左上角格子的坐标为(1,1),最右下角格子的坐标为(w,h)。接下来的若干行,每行有四个数x1,y1,x2,y2,且满足1=x1,x2=w,1=y1,y2=h,表示两张牌的坐标(这两张牌的坐标总是不同的)。如果出现连续四个0,则表示输入结束。【输出】对于每一对牌输出占一行,为连接这一对牌的路径最少包含的线段数。如果不存在路径则输出0。【输入样例】【输出样例】5 4 4 XXXXX 3 X X 0 XXX XXXX 2 3 5 31 3 4 42 3 3 40 0 0 0【输入】第一行有两个整数w,h(1=w,h=75)
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 施工组织


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!