ImageVerifierCode 换一换
格式:DOCX , 页数:32 ,大小:43.67KB ,
资源ID:26961136      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/26961136.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(图的广度优先搜索的应用.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

图的广度优先搜索的应用.docx

1、图的广度优先搜索的应用图的广度优先搜索的应用 内容提要广度优先搜索是分层次搜索,广泛应用于求解问题的最短路径、最少步骤、最优方法等方面。本讲座就最短路径问题、分酒问题、八数码问题三个典型的范例,从问题分析、算法、数据结构等多方面进行了讨论,从而形成图的广度优先搜索解决问题的模式,通过本讲座的学习,能明白什么样的问题可以采用或转化为图的广度优先搜索来解决。在讨论过程中,还同时对同一问题进行了深层次的探讨,进一步寻求解决问题的最优方案。 知识讲解和实例分析和深度优先搜索一样,图的广度优先搜索也有广泛的用途。由于广度优先搜索是分层次搜索的,即先将所有与上一层顶点相邻接的顶点搜索完之后,再继续往下搜索

2、与该层的所有邻接而又没有访问过的顶点。故此,当某一层的结点出现目标结点时,这时所进行的步骤是最少的。所以,图的广度优先搜索广泛应用于求解问题的最短路径、最少步骤、最优方法等方面。本次讲座就几个典型的范例来说明图的广度优先搜索的应用。先给出图的广度优先搜索法的算法描述:变量名表示含义F队列首指针R队列尾指针W该层顶结点的数目数组L队列数组b该结点的前趋指针数组c生成该结点的操作数H搜索树的层数Gh第h层首结点的位置编号F:=0;r:=1;Lr:=初始值;H:=1;w:=1;bb:=true;While bb do begin H:=h+1;gh:=r+1; For I:=1 to w do Be

3、ginF:=f+1; For t:=1 to 操作数 do Begin m:=Lf; 出队列;判断t操作对m结点的相邻结点进行操作;能则设标记bj:=0,并生成新结点;不能,则设标记bj:=1;if bj:=0 then 表示有新结点生成 begin for k:=1 to gh-1 do if Lk=新结点 then 判断新扩展的结点是否以前出现过 begin bj:=1;k:=gh-1 end;if bj1 then 没有出现过 begin r:=r+1;Lr:=新结点;新结点进队列 br:=f;cr:=t;并链接指针,保存操作数 end; end;end; end; w:=r+1-gh;

4、s:=0;计算新生成的一层的结点数 for k:=gh to r do 在新生成的一层结点中,判断是否有目标结点存在 if Lk=目标结点 then begin s:=s+1; 累计解的条数 根据链接指针求出路径; end; if s:0 thenbegin 输出s条路径; bb:=false; 设程序结束条件end;end;例1:最短路径问题求从任意一个顶点Vi出发,对给出的图,求到达任意顶点Vj(ij)的所有最短路径问题分析1、首先用邻接表表示此图各端点的邻接关系。顶点接邻顶点个数1234321373312454413635367846458372583856732、数据结构 const

5、d:array1.8,1.4 of byte=(2,3,4,0),(1,3,7,0),(1,2,4,5),(1,3,6,0),(3,6,7,8),(4,5,8,0),(2,5,8,0),(5,6,7,0) 二维数组存放邻接表 n:array1.8 of byte=(3,3,4,3,4,3,3,3); 存放邻接顶点数var L:array1.64 of byte 队列 F,r:byte f队头指针,r队尾指针 B:array1.64 of byte 链接表,表示某一个结点的前趋结点 G:array1.10 of byte 表示层结点的首结点在队列开始的位置 H:byte 搜索的层次由于搜索过的点

6、不再进行搜索,故设置一个数组EM为标记,表示结点M是否访问过e:array1.8 of 0.1;用1表示已访问过,0表示还没有访问c:array1.8,1.8of byte; Cs,j存储到达目标结点后各最短路径的线路bb:Boolean 搜索结束标记3、算法描述设立初值,并令起始结点进队:f:=0;r:=1;lLr:=st,Est:=1;w:=1;h:=1;将此时第h层(开始h=1,表示第一层)的w(开始时w=1,表示一个结点)顶点的顺序出队,并访问与该层各顶点相邻接但又没有访问过的顶点,同时将这些结点进队列,且设立前趋链接指针和访问过标记,若此时的结点为目标结点,则只设立前趋链接指针而不设

7、立访问过标记计算此时第h+1层的顶点个数w:=r+1-gh,然后看该层有多少个顶点为目标结点,凡是出现目标顶点的,就将其个数累计,也就是为最短路径的条数,同时从这个目标结点按前趋链接指针将到达该目标结点的路径的各个顶点编号存入cs,j中,然后转,若目标顶点累计个数为0,表明该层没有出现目标结点,则转。打印搜索到的各条最短路径的各结点编号,并结束程序。程序如下:(见exp7_1.pas)program exp7_1; constd:array1.8,1.4 of byte=(2,3,4,0),(1,3,7,0),(1,2,4,5),(1,3,6,0),(3,6,7,8),(4,5,8,0),(2

8、,5,8,0),(5,6,7,0); n:array1.8 of byte=(3,3,4,3,4,3,3,3); varL,b:array1.64 of byte; F,r,h,m,st,ed,I,j,t,k,s,p,w:byte; G:array1.10 of byte;e:array1.8 of 0.1;c:array1.8,1.8of byte;bb:Boolean; begin write(start:);readln(st); write(end:);readln(ed); fillchar(e,sizeof(e),0); 标记数组清零 fillchar(c,sizeof(c),0)

9、; 路径数组清零 f:=0;r:=1;Lr:=st;h:=1;w:=1;bb:=true; while bb do begin h:=h+1;gh:=r+1; 记录h+1层的首地址 for i:=1 to w do begin f:=f+1;m:=Lf;em:=1; 取队首结点,并设访问过标记 for t:=1 to nm do 依次访问m结点的相邻结点 if edm,t=0 then 若m的相邻结点没有访问过 begin r:=r+1;Lr:=dm,t;br:=f; 则进队列 end; end; w:=r+1-gh; 计算第h层的新结点数目s:=0;for k:=gh to r do 检查第

10、h层上的新结点是否存在目标结点if Lk=ed then 等于目标结点 begin s:=s+1;p:=bk;j:=1; cs,j:=Lk; while p1 do begin j:=j+1;cs,j:=Lp;p:=bp; end; j:=j+1;cs,j:=Lp; for t:=j downto 1 do if t=1 then writeln(cs,t) else write(cs,t,); end; if s0 then begin writeln(st,ed,total=,s,step=,j-1); bb:=false; end; end;end.输入:start:1end:8输出:1

11、2781358146818 total=3 step=3输入:start:2end:6输出:21462346235627562786214626 total=5 step=3推广应用(作业题1):如下图表示的是从城市A到城市H的交通图,从图中可以看出,从城市A到城市H要经过若干个城市。现要找出一条经过城市最少的一条路线。例2:分酒问题有一8斤酒瓶装满酒,没有量器,只有两个分别能装5斤和3斤的空酒瓶。试设计一程序将8斤酒对分为两个4斤,并以最少的步骤给出答案。问题分析1、 分析要解决分酒问题,先将所有倒酒的可能性全列出来,如下表:操作数Bi123456操作Dk858358533835在倒酒过程中

12、,看起来是每一次倒酒,上面的六种操作都可能进行,然而有此操作却是无意义的。如8斤瓶空时,则83、85是无意义的。又如8斤瓶满时,则58、38操作无意义。因此,每次倒酒操作后,都必须知道此时三个酒瓶到底多少酒,这样才能准确判断此时何种操作不能进行,何种操作可以进行。为了表示每操作一次后各酒瓶中的酒量,设变量M表示8斤瓶在进行第i操作后装的酒量,N表示5斤瓶在进行第i操作后装的酒量,A表示3斤瓶在进行第i操作后装的酒量,由于整个酒量为8,所有A=8-M-N。对以上六种操作能和不能进行的条件如下:85操作:不能进行的条件为:N=5或M=0 能进行时,剩余量为:N=N+M,此时如果N5,则M=N-5,

13、N=5,否则M=083操作:不能进行的条件为:8-N-M=3或M=0 能进行时,剩余量为:如果M3-(8-M-N),则M=0,否则M=5-N,N不变58操作:不能进行的条件为:M=8或N=0 能进行时,剩余量为:M=N+M且N=053操作:不能进行的条件为:8-N-M=3或N=0 能进行时,剩余量为:如果N5,8-3,5-8,5-3,3-8,3-5); 6种操作var L:array1.50,1.2 of shortint; 表示倒酒后8斤和5斤瓶中的剩余量 B:array1.50 of shortint; 每一层的各结点的前趋结点的链指针 C: array1.50 of shortint;

14、每进行一次操作的操作数 E:array1.10,1.20 of shortint;最少步骤的所有解中,该层各结点是由上一层各结点通过何种操作而得到的操作数 X,y:array1.10,1.20 of shortint ;在最少步骤所有解中,各层的结点其8斤和5斤瓶中的剩余量 G:array1.20 of shortint; 各层结点的首结点在队列的位置 F,r,h,w,n,m:shortint; f为队列首指针,r为队列尾指针,m,n分别表示8斤和5斤瓶中的剩余量,h为搜索的层数,w为每一层结点的个数3、 算法描述:设立队首队尾指针初值,f=0,r=1。并使开始状态的结点入队,L(r,1)=8

15、,同时设立其它初值:h=1,gh=r,w=1。取队列首结点,对该状态分别进行六种操作,并用对六种操作能否进行的条件进行判断,若能进行此操作,则计算进行这种操作后8斤、5斤和3斤瓶中各自的数量,同时将此时的各瓶剩量和上一层以前的各结点进行比较,相同则不产生该结点,即换另一操作并进行刚才相同的判断;若不同,则将此时产生的结点进入队列,然后继续取另一种操作再重复刚才的过程。当六种操作能否进行的判断完成之后,则对所产生的该层的所有结点进行判断,是否已出现目标结点,若出现目标结点,则将此时的一条最少步骤的解的各结点进行链指针的链接,并将链接的各结点存于数组xs,i和ys,i中,同时将到达该结点所进行的操

16、作的操作数存于es,i中,同时累计出现目标结点的个数s,并判断s的值是否为0,若s=0则表明没有出现目标结点,转;否则继续打印输出s种最少步骤的最优解的方案。4、 程序清单:(见exp7_2.pas)program exp7_2; uses crt; const d:array1.6 of string4=(8-5,8-3,5-8,5-3,3-8,3-5); var L:array1.50,1.2 of shortint; b,c:array1.50 of shortint; e,x,y:array1.10,1.20 of shortint; g:array1.20 of shortint;

17、f,r,w,h,n,i,m,t,a,bj,s,k:shortint; b1:boolean; procedure fpro(k,h:byte); 根据链指针找出解路径 var i,p:byte; begin p:=k; for i:=h downto 1 do begin xs,i:=Lp,1;ys,i:=Lp,2; es,i:=cp;p:=bp; end; end; begin f:=0;r:=1;h:=1;Lr,1:=8;Lr,2:=0;不开 初值入队列 w:=1;b1:=true;a:=0; while b1 do begin h:=h+1;gh:=r+1; 记录第h+1层的首位置 fo

18、r i:=1 to w do 将原第h层的w个结点逐个扩展 begin f:=f+1; 移首指针 for t:=1 to 6 do 逐一尝试六种操作 begin m:=Lf,1;n:=Lf,2; 取首指针的结点 case t of 判断对首结点状态哪种操作能进行 1:8-5 表示是8斤瓶倒5斤瓶 if (m=0) or (n=5) then bj:=1 不能操作,设标记bj为1 else begin 能操作,设bj为0,并计算倒出后各瓶的数量 n:=n+m;bj:=0; if n5 then begin m:=n-5;n:=5;end else m:=0; end; 2:8-3 begin a

19、:=8-m-n; 计算3斤瓶中的酒量 if (m=0) or (a=3) then bj:=1 else begin bj:=0; if m8 if (m=8) or (n=0) then bj:=1 else begin m:=m+n;n:=0;bj:=0 end; 4:5-3 begin a:=8-m-n; if (n=0) or (a=3) then bj:=1 else begin bj:=0; if n8 begin a:=8-m-n; if (m=8) or (a=0) then bj:=1 else begin m:=8-n;bj:=0 end; end; 6:3-5 begin

20、 a:=8-m-n; if (n=5) or (a=0) then bj:=1 else begin bj:=0; if a(5-n) then n:=5 else n:=8-m; end; end; end; if bj=0 then 表示有新结点生成 Begin for k:=1 to gh-1 do 检查新结点是否已出现过 if (Lk,1=m) and (Lk,2=n) then begin bj:=1;k:=gh-1;end; if bj1 then 说明以前没有出现新结点 begin 新结点进队列,并链接指针,保存操作 r:=r+1;Lr,1:=m;Lr,2:=n;br:=f;cr

21、:=t end; end; end; end; w:=r+1-gh;s:=0; 计算已生成的第h层的结点总数 for k:=gh to r do if (Lk,1=4) and (Lk,2=4) then begin s:=s+1; fpro(k,h) 第h层若出现目标结点则找出路径 end; if s0 then 说明路径存在,打印路径 begin clrscr;writeln(best answer); writeln(step:5,operate:15,8p:6,5p:6,3p:6); for t:=1 to s do begin for k:=1 to h do begin a:=8-

22、xt,k-yt,k; if k=1 then writeln(k-1:4,:,xt,k:20,yt,k:6,a:6) else writeln(k-1:4,:,det,k:15,xt,k:5,yt,k:6,a:6); end end; b1:=false; end; end;end.输出结果(略)推广应用:1、有一10斤酒瓶装满酒,没有量器,只有两个分别能装7斤和3斤的空酒瓶。试设计一程序将8斤酒对分为两个5斤,并以最少的步骤给出答案。进一步:有一x斤酒瓶装满酒,没有量器,只有两个分别能装y斤和z斤的空酒瓶(其中xyz,且x=y+z)。试设计一程序将x斤酒对分为两个x/2斤,并以最少的步骤给出

23、答案。(作业题2)思考:有两个无刻度标志的水壶,分别可装x升和y升(x,y为整数,x、y=100)的水。设另一方面有一水缸,可用来向水壶灌水或倒出水,两水壶间,水也可以相互倾灌。已知x升为满壶,y升为空壶。问如何通过倒水或灌水操作用最少步数能在y升壶中量出z(z=100)升的水来。(作业题3)例子3:八数码问题如下图所示,给出33的九个方格,现将18这八个自然数填入方格中,给定一个初始状态,例如为:283104765(如图),其中空方格用数字0表示。现允许移动空格,但每次只能移动1格。试编一程序完成对于任意给定的一个目标状态(如下图),能够以最少步数实现从初始状态到目标状态的转换。123804

24、7652831047651、 问题分析:由于空格要进行移动,所以,我们先将方向和移动量表示如下: 124移动方向1234Di0-101Dj-10103我们可以用广度搜索法来解决。由于广度搜索算法是分层进行的,当搜索的层次越深,每一层的结点数量几乎是以几倍甚至几十倍的数量增加,由于受到内存的影响,所以该程序定义的数组只适合解决目标结点在十一、十二层处。2、 定义数据结构:const di:array1.4 of integer=(0,-1,0,1);列的方向移动量 dj:array1.4 of integer=(-1,0,1,0);行的方向移动量 d:array1.3,1.3 of intege

25、r=(1,2,3),(8,0,4),(7,6,5);目标状态各结点的位置var L:array1.3000,1.3,1.3 of integer;存放能有效移动的各结点 C:array1.30,1.3,1.3 of integer;存放各层通往目标结点的各结点 A:array1.3,1.3 of integer;初始和变化过程中的八数码各结点的位置 B:array1.3000 of integer;各结点的前趋结点位置的链指针 G:array1.100 of integer;队列中各层首结点在队列中的位置 F,r:integer;队首和队尾的指针 H:integer;层数 W:integer;

26、每层结点个数3、算法描述: 输入要排的八数码初始值,并设立队首队尾指针的初值:f:=0;r:=1;h:=1;w:=1;gh:=r;将八数码初始值取出放入a数组中,同时将初值的各结点的数据入队列;层次加1:h:=h+1;并记录首结点的位置:gh:=r+1;将h-1层的w个结点逐一取出,即先移动队首指针:f:=f+1;然后将f指针位置上的结点各数据Lf,t,j取出,分别赋给at,j,并记录空格所在的位置坐标x,y(列和行)。然后,在该位置上按空格移动的四个方向顺序移动,并检查哪个方向为有效的移动(无效移动就是移动后出现以前的状态),并将有效移动后的各结点值入队;生成为第h层的各结点,并继续。计算第

27、h层的结点总数w:=r+1-gh,并对第h层的各结点进行判断,检查是否出现了目标结点,若没有出现目标结点,则转;若出现目标结点,则进行各层次的解的路径指针值的链接,并转打印从初始结点到目标结点各层的移动方案。4、程序清单:(见exp7_3.pas)program exp7_3; const di:array1.4of integer=(0,-1,0,1); dj:array1.4 of integer=(-1,0,1,0); d:array1.3,1.3 of integer=(1,2,3),(8,0,4),(7,6,5); var a:array1.3,1.3 of integer; c:array1.30,1.3,1.3

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1