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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

八数码的几种解决方法.docx

1、八数码的几种解决方法八数码的几种解决帖子关于是八数码的,是前段时间写的,为了给别人一些搜索的样例。现在,事差不多完了,代码还留着,觉着放着浪费,又想自己水平过于欠缺,再加上看在C吧的初学者还是占主要,就觉得发在此处共他们学习还是不错的,仅此而已。 如果有不知道八数码的问题的,可以上网一搜,就什么都明白了。在这里我只用了几种算法实现,其实还有其他方法,我并没有写(如果有人需要,可能我会重新完成)。 首先分析下八数码的一些算法吧。 1:深度优先(DFS): 这个方法起始对八数码非常不好,问题在于搜索过于盲目,搜索深度如果没有限制,有些是根本没必要的(因为八数码的解,大部分集中在2030步之间)。而

2、且即使搜索到一个解,很可能不是最优解。所以用DFS解决这个问题并不明智,不过为了显示其不好,我仍然实现,不过在程序中设置最大深度限制为100。 2:宽度优先搜索(BFS) 宽度优先搜索,解决的还不错,经过对hash函数的优化,能使一个2030步的解在200300MS内解决(不过其还可以做进一步的优化)。 3:迭代加深搜索 迭代加深搜索,可以说是吸取了宽搜和深搜的优点,同时避免了深搜搜到第一个解的不最优性,和宽搜的使用较大的内存空间。 在这里我也用迭代加深搜索,仔细一看的人就发现,起使他只是在深搜上稍微做点“手脚”就完毕,但是其思想,虽然显而易见,可我觉得并不容易想到(指当初提出这个算法的时候)

3、。 4:爬山法 爬山法,经常在人工只能里面见得到,由于其高效,实现简单,所以其有时也是很有用的。但是爬山法,也有缺点,就是搜到的解只是局部最优解,而且有陷入“无解”的风险。爬山法,顾名思意就是一直沿着“最好的方向走”直到“山顶”,就找到解。爬山法,不像回溯,在遍历节点时不保存其他非当前最优节点,也就是说,一旦走错了,就不能再后头搜索其他方向。 所以在我写的爬山法中,对于一个解,虽然很多100多步,但是所需的时间确实0MS左右。 5:双向搜索 双向搜索,前后来搜,碰到头,然后一拼接就出了路径。其搜索的节点数要明显必宽搜少许多,所以在程序中,我并未对其做任何优化,他搜索一个解的时间基本上是0MS。

4、 6:A*算法 A*算法,不用说,解决这个问题很简单。速度也快,都是0MS。具体的可以参考网上的解释。 7:DIA算法 DIA算法可以说是A*与迭代搜索的结合,思想来源于迭代搜索,其实简单的说就是,迭代搜索添加了估价函数。由于时间,当初我并未用该方法实现。第一个贴的代码是宽搜,由于在hash上做了优化,所以对hash部分做下解释: * 对于一个状态,转换为123405678这样的序列,然后分别对应权值: 0:8!,1:7!2:6!,.,8:0! 然后用每个数的逆序数乘上权值的和即为改状态的hash表对应的下标。 对于上序列对应的hash下标为:4*8!+0*7!+0*6!+0*5!+0*4!+

5、0*3!+0*2!+0*1!+0*0!=161280 - 另外对于这种hash值计算外,还有一个由上一个状态来推到下一个状态的hash值的规律: 假设,移动是有从空格的移动方向来看,并且设空格在序列中的位置为i,并且是index为上一个状态的hash值,则下一个状态的hash值为: 上移:index-3*8!+ai-3!*(ai-1ai-3+ai-2ai-3)-ai-2!*(ai-2ai-3)-ai-1!*(ai-1ai+3+ai+2ai+3)+ai+2!*(ai+2ai+3)+ai+1!*(ai+1pi-3)?(Factorialpi-3):(-Factorialpi-2); newinde

6、x+=(pi-1pi-3)?(Factorialpi-3):(-Factorialpi-1); 下移: newindex+=3*40320; newindex-=(pi+2pi+3)?(Factorialpi+3):(-Factorialpi+2); newindex-=(pi+1pi+3)?(Factorialpi+3):(-Factorialpi+1); 因此,对于此种hash值的计算,最多只需要3次加减法,2次比较(平均约2次加减法,3.5次比较运算)运算即可完成hash值的计算,而且这种计算出来的hash值不存在冲突。. *宽搜代码如下: #include #include #incl

7、ude #include #include usingnamespacestd; #defineHashTableSize362880 #defineNOT! typedefstructmaps intdetail33; intparent;/记录父节点在hash表中的位置 intmyindex;/记录自己节点在hash表中的位置 intx,y;/记录空格(0)的坐标 Map,*PMap; Maporg;/初始状态 Mapend;/目标状态 PMapHashTableHashTableSize=NULL;/hash表 charRpath150;/最终的路径 intconstderection4

8、2=-1,0,1,0,0,-1,0,1;/可移动的四个方向 boolFlageNew; /* * *八数码的输入(在这里不做任何输入检查,均认为输入数据是正确的) * */ voidinput() inti,j; intsum; for(i=0;i9;i+) scanf(%1d,*org.detail+i); if(0=*(*org.detail+i) org.x=i/3; org.y=i%3; org.parent=-1; for(i=0;i9;i+)/计算逆序 if(0=*(*org.detail+i) continue; for(j=0;ji;j+) if(0!=*(*org.detai

9、l+j)&*(*org.detail+j)*(*org.detail+i) sum+; if(sum%2=0)/目标状态各个数字对应的坐标位置 end.detail00=1,end.detail01=2,end.detail02=3; end.detail10=4,end.detail11=5,end.detail12=6; end.detail20=7,end.detail21=8,end.detail22=0; else end.detail00=1,end.detail01=2,end.detail02=3; end.detail10=8,end.detail11=0,end.detai

10、l12=4; end.detail20=7,end.detail21=6,end.detail22=5; return; /* * *检测两个状态是否一样 * */ inlineboolIsEqual(Mapa,Mapb) return0=memcmp(constvoid*)(*a.detail),(constvoid*)(*b.detail),36); /* * *hash值的计算 * */ intHashValue(Mapa) intcount; inti,j; intvalue=0; staticintpv9=1,1,2,6,24,120,720,5040,40320; for(i=0;

11、i9;i+) for(j=0,count=0;ji;j+) if(*(*a.detail+i)*(*a.detail+j) count+; value+=pvi*count; returnvalue; /* * *状态插入到hash表中。返回的是插入到的hash表中对应的下标值 * */ intInsertHashTable(Mapa,intparent) intindex=HashValue(a); if(NULL=HashTableindex)/如果为TURE,那么说明hash表中不存在该状态,应该插入到hash表中 a.parent=parent; HashTableindex=newM

12、ap; *HashTableindex=a; FlageNew=true; else FlageNew=false; returnindex; /* * *宽度优先搜索 * */ voidBfs() queueQueue; boolFinish=false; org.myindex=InsertHashTable(org,-1); Queue.push(org); while(false=Queue.empty()&NOTFinish) Mapnode=Queue.front(); Queue.pop(); /printf(%dn,Queue.size(); if(true=IsEqual(n

13、ode,end) Finish=true; end.parent=node.parent; end.myindex=node.myindex; continue; for(intk=0;k4;k+) Maptmp=node; tmp.x=node.x+derectionk0, tmp.y=node.y+derectionk1; if(tmp.x2|tmp.y2) continue; tmp.detailnode.xnode.y=tmp.detailtmp.xtmp.y;/移动空格 tmp.detailtmp.xtmp.y=0; inttmpindex=InsertHashTable(tmp,n

14、ode.myindex); if(false=FlageNew)/如果不是新状态的,即以前访问过改节点,不再加入队列中 continue; tmp.parent=node.myindex; tmp.myindex=tmpindex; Queue.push(tmp); return; /* * *通过hash表中记录的进行查找路径 * */ voidFindPath() Mapnow; stackStack; Stack.push(end); now=end; intcount=0; while(now.parent!=-1) Stack.push(*HashTablenow.parent);

15、now=Stack.top(); printf(共需:%d步n,Stack.size()-1); getchar(); while(NOTStack.empty() now=Stack.top(); Stack.pop(); for(inti=0;i3;i+) for(intj=0;j3;j+) printf(%3d,now.detailij); printf(n); if(0!=Stack.size() printf(n第%d步n,+count); getchar(); printf(nTheEnd!n); return; intmain() input(); longtime=GetTic

16、kCount(); Bfs(); printf(计算用时:%dMSn,GetTickCount()-time); FindPath(); return0; 接下来的第二个代码是: 深度优先搜索(限制了他的深度为50) #include #include #include #include #include usingnamespacestd; #defineHashTableSize362880 #defineNOT! #defineMaxDeep50 typedefstructmaps intdetail33; intx,y;/记录空格(0)的坐标 Map,*PMap; Maporg;/初始

17、状态 Mapend;/目标状态 boolHashTableHashTableSize=false;/hash表 intconstderection42=-1,0,1,0,0,-1,0,1;/可移动的四个方向 intPathMaxDeep+1; intStep; boolFinish; /* * *八数码的输入(在这里不做任何输入检查,均认为输入数据是正确的) * */ voidinput() inti,j; intsum; for(i=0;i9;i+) scanf(%1d,*org.detail+i); if(0=*(*org.detail+i) org.x=i/3; org.y=i%3; f

18、or(i=0;i9;i+)/计算逆序 if(0=*(*org.detail+i) continue; for(j=0;ji;j+) if(0!=*(*org.detail+j)&*(*org.detail+j)*(*org.detail+i) sum+; if(sum%2=0)/目标状态各个数字对应的坐标位置 end.detail00=1,end.detail01=2,end.detail02=3; end.detail10=4,end.detail11=5,end.detail12=6; end.detail20=7,end.detail21=8,end.detail22=0; else end.detail00=1,end.detail01=2,end.detail02=3; end.detail10=8,end.detail11=0,end.detail12=4; end.detail20=7,end.detail21=6,end.detail22=5; return; /* * *检测两个状态是否一样 * */ inlineboolIsEqual(Mapa,Mapb) return0=memcmp(constvoid*)(*a.detail),(constvoid*)(*b.detail),36); /*

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

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