用回溯法求解一般哈密尔顿回路问题_第1页
用回溯法求解一般哈密尔顿回路问题_第2页
用回溯法求解一般哈密尔顿回路问题_第3页
用回溯法求解一般哈密尔顿回路问题_第4页
用回溯法求解一般哈密尔顿回路问题_第5页
已阅读5页,还剩24页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、目 录 引言- 1 -1 需求分析- 2 -1.1问题的提出- 2 -1.2问题的描述- 2 -1.3算法的描述- 3 -2 概要设计- 4 -2.1系统运行环境- 4 -2.2算法的实现- 4 -2.3接口设计- 12 -2.4出错处理设计- 12 -2.5维护设计- 13 -3 详细设计- 14 -3.1算法的分析- 14 -3.2程序的思路- 15 -3.3程序的实现- 15 -3.4设计环境- 19 -4 调试分析- 20 -4.1有哈密尔顿回路连通图- 20 -4.2无哈密尔顿回路连通图- 22 -5 总结- 23 -参考文献- 25 -附录- 26 - 摘 要 回溯法是一种按照深度

2、优先的策略从根结点开始搜索解空间树的算法,该算法既带有系统性又带有跳跃性,它在包含问题的所有解的解空间树中,按照深度优先的策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一节点时,总是先判定该节点是否肯定不包含问题的解,如果肯定不包含,则跳过对以该节点为跟的子树的系统搜索,逐层向其祖先节点回溯。否则,进入该子树,继续按深度优先的策略进行探索。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法。回溯法可以用来求出问题的全部解,也可以在求出问题的一个解之后停止对问题的求解,即只求该问题是否有解。它适用于解一些组合数较大的问题。哈密尔顿回路路就是判断图中是否存在一条通过所有顶点一次且仅一次

3、的路径。本文主要讲的就是用回溯法来求解一个任意的图中是否存在一条哈密顿通路的问题,并用具体的算法来实现它。 关键词:回溯法 哈密尔顿回路 空间树 引言回溯法是一个既带有系统性又带有跳跃性的的搜索算法。它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点出发搜索解空间树1。算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解。如果肯定不包含,则跳过对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯。否则,进入该子树,继续按深度优先的策略进行搜索。回溯法在用来求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜索遍才结束 2。而回溯法在用来求问题的任一解时,只要搜

4、索到问题的一个解就可以结束。这种以深度优先的方式系统地搜索问题的解的算法称为回溯法,它适用于解一些组合数较大的问题。 1 需求分析1.1问题的提出 在求解一些问题(如走迷宫、地图着色等问题)时,题目的要求可能是求出原问题的一种或所有可能的解决方案。这类问题的解往往是由一个一个的步骤或状态所构成的,每一步骤又有若干种可能的决策方案;由于没有固定、明确的数学解析方法,往往要采用搜索的做法,即从某一个初始状态出发,不断地向前(即下一个状态)搜索,以期最终达到目标状态,从而得到原问题的一个解或所有的解。在搜索的过程中,由于问题本身及所采取的搜索方法的特点(如在缺乏全局及足够的前瞻信息的情况下进行搜索等

5、)3,会导致走到某一状态就走不下去的情况,这时,就必须回头(即回到上一步,而不是回到最初的状态),再尝试其 他的可能性,换一个方向或方法再试试。这样,不断地向前探索、回溯,再向前、再回溯,直至最终得出问题的解,或者一路回溯到出发点(出现这种情况即表示原问题无解)4 。注意,这种搜索过程并不是尝试搜索问题解空间中所有的可能状态和路径,而是采用深度优先的方式,沿着一条路径,尽可能深入地向前探索。1.2问题的描述1设计内容:给出内存分类法的多种应用,给出这些应用对应的算法并编程实现。2设计要求:(1)给出各种分类法的求解算法;(2)编程实现各种分类法的算法;(3)对所写的每个算法给出时空复杂性分析。

6、1.3算法的描述 该算法讲的就是用回溯法求解一个无向图中是否存在哈密尔顿回路的问题。所谓哈密尔顿回路就是指经过图(有向图或无向图)中所有顶点一次且仅一次的通路。用回溯法解哈密尔顿回路问题首先要画出问题的解空间树,该解空间树是一棵最大度是 n 的树(其中 n 为图中的顶点数),树中只有第一个结点的度是 n,其余结点的度都为 n-1(该结点不用与其自身相连)。在编写算法时可以通过判断该边在图的邻接矩阵中的值来剪枝,如果其值不是 1 则说明该边不存在则剪枝不用搜索。由于在求图的哈密尔顿回路时走过的顶点不能再重复走,所以要对已经遍历过的顶点做一个标记,如果在搜索时找到的是一个带有标记的顶点,那么该路径

7、也是不可行的,应剪去。2 概要设计此算法设计为用回溯法求解一般哈密尔顿回路问题,设计的主要内容为:给出内存分类法的多种应用,给出各类分类法的求解算法,编程实现各种分类法的算法,对所写的每一个算法给出时间空间复杂性分析。2.1系统运行环境根据目前市场上能够提供的硬件。我们设计系统的硬件环境如下:l IBM PC286及以上档次微机、便携机、各种品牌兼容机,最佳档次为386以上微机。l 512M或512M以上内存,最好具备扩展内存l EGA、VGA、TVGA、所有SUPERVGA彩色显示器。l 20M以上硬盘。l 任何光电鼠或机械鼠。软件环境如下:l MS(PC)DOS3.3或以上版本;l 采用V

8、C+进行开发;2.2算法的实现1.个体类class Cind public:int& operator ( int index ) return dataindex; Cind & Cind:operator = (Cind &a);bool operator = (Cind &ind);void CrossWith(Cind &a);void Mut();void show();void SetArc();double fun();Cind();virtual Cind();int * data;static int n;double fitness;

9、/ ind.cpp: implementation of the Cind class./#include "stdafx.h"#include "GrWndapp.h"#include "shapelist.h"#include "ind.h"#include "node.h"#include "arc.h"#include "math.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE=_FILE_

10、;#define new DEBUG_NEW#endifint Cind:n;extern CShapeList node_list,arc_list;/ Construction/DestructionCind:Cind()data = new intn;bool * flag = new booln;for ( int i=0; i<n; i+ )flag= true;int k=0;for ( int m=n; m>0; m- )int t = rand()%m;int j = 0;for ( i = 0; i<n; i+ )if ( flag )if ( j = t

11、)datak+ = i;flag =false;break;j+;delete flag;Cind:Cind()delete data;double Cind:fun()double v = 0;CNode * pn1,*pn2;for ( int i=0; i<n-1; i+ )pn1 = (CNode *)node_list.GetShape(data);pn2 = (CNode *)node_list.GetShape(datai+1);v += sqrt(pn1->x - pn2->x)*(pn1->x - pn2->x)+(pn1->y-pn2-&

12、gt;y)*(pn1->y-pn2->y);pn1 = (CNode *)node_list.GetShape(data0);v += sqrt(pn1->x - pn2->x)*(pn1->x - pn2->x)+(pn1->y-pn2->y)*(pn1->y-pn2->y);return v;void Cind:SetArc()arc_list.Clear();CArc * parc;for ( int i=0; i<n-1; i+ )parc = new CArc(CNode *)node_list.GetShape(da

13、ta),(CNode *)node_list.GetShape(datai+1);arc_list.Add(parc);parc = new CArc(CNode *)node_list.GetShape(data),(CNode *)node_list.GetShape(data0);arc_list.Add(parc);void Cind:show()TRACE("The ind:n");for ( int i=0; i<n; i+ )TRACE ( "%d->",data );TRACE("n");void Cind

14、:Mut()int p1 = rand() % n;int p2 = rand() % n;int t = datap1;datap1=datap2;datap2=t;void Cind:CrossWith(Cind &a)int pos = rand() % (n-1);pos +;int * t1, * t2;t1 = new intn;t2 = new intn;int k=0;for ( int i=0; i<n; i+ )for ( int j=0; j<pos; j+ )if ( data = aj )break;if ( j = pos ) / find no

15、net1k+ = data;for ( i=0; i<pos; i+ )t1k+ = a;k=0;for ( i=0; i<n; i+ )for ( int j=0; j<pos; j+ )if ( dataj = a )break;if ( j = pos ) / find nonet2k+ = a;for ( i=0; i<pos; i+ )t2k+ = data;for ( i=0; i<n; i+ )data = t1;a = t2;delete t1;delete t2;Cind & Cind:operator =(Cind &a)if

16、( this = &a )return * this;for ( int i=0; i<n; i+ )data=a;fitness=a.fitness;return * this;bool Cind:operator =(Cind &ind)for ( int i=0; i<n; i+ )if ( data != ind )return false;return true;2.群体类#include "ind.h"class CGroup public:void Reserve();void Grow();Cind * GetBest();voi

17、d Select();void CalFitness();CGroup();virtual CGroup();int n,m,ml;Cind * group;Cind * pool;int nres;static int gn; / group lengthstatic double miu;static double gg; / gerneration gapstatic double pmut; / probability of mutantstatic double pres; ;/ Group.cpp: implementation of the CGroup class./#incl

18、ude "stdafx.h"#include "GrWndapp.h"#include "Group.h"#include "shapelist.h"#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE=_FILE_;#define new DEBUG_NEW#endifextern CShapeList node_list,arc_list;int CGroup:gn;double CGroup:gg;double CGroup:miu;double CGroup:

19、pres;double CGroup:pmut;/ Construction/Destruction/CGroup:CGroup()gn=100; / group lengthpmut=0.3;pres = 0.1;srand( (unsigned)time( NULL ) );Cind:n = node_list.n;group = new Cindgn;pool = new Cindgn;nres = gn*pres;CGroup:CGroup()delete group;delete pool;void CGroup:CalFitness()double maxfst=0;for ( i

20、nt i=0; i<gn; i+ )group.fitness=group.fun();maxfst=_max(maxfst,group.fitness);for ( i=0; i<gn; i+ )group.fitness=maxfst-group.fitness;void CGroup:Select()CalFitness();/ calculate the sum of fitness of the individuldouble sum=0;for ( int i=0; i<gn; i+ )sum += group.fitness;/ create a positio

21、nfor ( i=0; i<gn-nres; i+ )double pos = rand()*sum/RAND_MAX;double t=group0.fitness;for ( int j=0; j<gn; j+ ) / find the indvidulif ( pos <= t )pool=groupj;break;elset += groupj+1.fitness;Cind * CGroup:GetBest()double v=group0.fun();Cind * pind = &group0;for ( int i=1; i<gn; i+ )if (

22、 group.fun() < v )pind = &group;v = group.fun();return pind; void CGroup:Grow()Select();Reserve();/ cross over-for ( int i=0; i<gn-nres; i+=2 )pool.CrossWith(pooli+1);group=pool;groupi+1=pooli+1;/ mutant-int num = gn * pmut; / 要变异的个体数for ( i=0; i<num; i+ )int ind = rand()%gn; / random s

23、electgroupind.Mut();void CGroup:Reserve()Cind t;for ( int i=0; i<nres; i+ )for ( int j=0; j<gn-1; j+ )if ( groupj.fitness > groupj+1.fitness )t=groupj;groupj=groupj+1;groupj+1=t;2.3接口设计1.外部接口(1) 用户界面采用图形用户界面(GUI),包含菜单、按钮、对话框等元素。(2) 软件接口软件运行于windows XP极其以上版本之上。(3) 硬件接口运行于IBM PC386及兼容机以上。2.4出

24、错处理设计1.系统应具有相当健壮性,避免或降低由系统错误所造成的损坏。2.对关键性操作。2.5维护设计系统严格按照设计规范进行设计,并保持各阶段文档的完整性,为以后对软件的维护打好基础。3 详细设计在以上工作的基础上,我们根据任务要求编程实现用回溯法求解一般哈密尔顿回路问题。对有输出要求的全部数据进行分析,进一步研究整个算法的实现。 3.1算法的分析各函数功能简要分析:函数 FirstAdjVex()用来求出图的邻接矩阵的某一行存在的第一条边所对应的第一个顶点;函数 NextAdjVex()用来求出跟第一个顶点在解空间树中同行相邻的下一个顶点;函数 initStatus()初始化跟踪栈,把所有

25、已经遍历过的并且当前已经符合条件的点都放在这里面;函数 backtrack()进行回溯;函数 bool testHami()判断一下该图有没有哈密顿通路;函数 Hami()是该算法的入口点,它通过调用函数 backtrack() 来实现层层递归。根据程序中判断哈密尔顿回路的条件对每一个节点访问一次且仅仅一次即visitTag0.N都等于 1,对 Hami(G)函数的简要分析: 1判断是不是连通图 2对每一个节点进行以下操作 (1) 初始化访问标志 visitTag (2) 调用试探每一个节点出发能不能找到哈密顿通路 ,如果能立即输出并跳出程序 3到这的时候说明不存在哈密尔顿回路3.2程序的思路

26、创建一个N节点的连通图输入顶点N的值输入连通图的边数创建每一条边,构成完整连通图求出哈密尔顿回路的所有解3.3程序的实现 #include<stdio.h>#include<process.h>#include<math.h>/全局变量声明int m=1; /用于标志哈密尔顿回路的总个数int n; /int x128;int graph128128;void nextvalue(int k)int j;while(1)xk=(int)fmod(xk+1,n+1);if(xk=0) return;if(graphxk-1xk)for(j=1;j<=k-

27、1;j+)if(xj=xk) break;if(j=k)if(k<n|(k=n&&graphxn1)return;void print(int x,int n)int i=1;printf("回路%d:",m);for(;i<=n;i+)printf("%d ",xi);printf("n");m+;void hamiltonian(int k)while(1)nextvalue(k);if(xk=0) return;if(k=n)print(x,n);elsehamiltonian(k+1);void m

28、ain()int i,j,e,a,b;printf("*哈密顿回路递归回溯算法*n");printf("*n");printf("请先创建一个n结点的连通图graphnnn");printf("请输入顶点n的值:");scanf("%d",&n);printf("图中一共有几条边?请输入以便我们创建图:");scanf("%d",&e);for(i=1;i<=n;i+)for(j=1;j<=n;j+)graphij=0;for(

29、i=1;i<=e;i+)printf("n创建第%d条边:n",i);printf("构成此边的一个顶点号(1%d):",n);scanf("%d",&a);printf("另一个顶点号(1%d):",n);scanf("%d",&b);graphab=graphba=1;x1=1;for(i=2;i<=n;i+)xi=0;printf("n以下为所求hamiltonian回路的所有解n");hamiltonian(2);3.4设计环境 操作系统:

30、Windows XP 设计工具:Microsoft Visual C+4 调试分析4.1有哈密尔顿回路连通图 1432564.2无哈密尔顿回路连通图 123545 总结通过本次课程设计,本人对算法设计与分析基础有了更深的认识,基本掌握了回溯法求解一般哈密尔顿回路的算法思路以及编程原理,提高了程序开发的能力,让能切实体会到算法在编程过程中的指导作用。通过课程设计,学会了按课程设计的任务要求完成各项程序的开发,对提高自身编程能力和项目管理能力有重要的现实意义。在本次课程设计中,由于对回溯法以及哈密尔顿回路的不熟悉,走了很多弯路,花了一些时间去了解其相关知识。但是最后终于完成了自己的课程设计,自己觉

31、得还是比较有成就感的。与此同时,我也发现用回溯法求解一般哈密尔顿回路问题是一个 np 问题,其时间复杂度是 O(n ),空间复杂度是 O(2 )。通过这次的课程设计,我学到了很多东西:1 多和别人交流,毕竟一个人所能想到的东西是有限的,但是通过和别人的交流,我发现我可以看到更多的东西了,例如:可能在程序的实现过程中,我并没有注意到程序在运行过程中会产生异常,但是在和别人的交流过程中,我发现了这个异常,促使我去捕获它,使所开发的系统有了更好的健壮性。2 一个程序的开发,需要开发人员用心去完成每一个阶段的工作,这样才不会出现开发到一半又忽然发现在某个地方出现了致命的错误,需要重新开发的严重错误,我

32、想这就好像是在编程的时候需要避免“回溯”是一个道理,前期多做些工作,后期的开发才会水到渠成,缩短开发周期。致谢能完成这个课程设计,我首先要感谢我的指导老师谭三老师,在他严格的监督和细心指导中,使我能够坚持完成本课程,并能够较好的实现要求任务书上所要求的功能,最后,我要感谢班上同学对我的帮助和指点。没有他们的帮助和提供资料对于我一个对编程知识不是很精通的人来说要想在短短的的时间里完成一个算法的设计是几乎不可能的事情。在此表示最诚挚的感谢!参考文献1算法设计与分析 宋 文等编 重庆大学出版社,2001。2算法设计与分析 周培德 电子工业出版社,2000。3算法设计与分析 王晓东 电子工业出版社,20044 李登信;关于 Cayley 图的 Hamilton 性的一个猜想J;渝州大学学报(自然科学版);1999 年 04 期5 百度网站 6 google网站 附录该算法的具体实现主要代码如下: int FirstAdjVex(const MGraph& G,int v)/查找 v 的第一个邻接点 for(int i=0;i<G.vexnum;i+) if(G.arcsvi.adj!=0) return i; return -1; int NextAdjVex(const MGraph& G,int v,int w)/查找 v 的(相对于 w 的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论