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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

回溯法求旅行售货员问题物联1301班刘悦08080112.docx

1、回溯法求旅行售货员问题物联1301班刘悦08080112算法分析与设计实验报告第 X次实验姓名刘悦学号201308080112班级物联1301班时间12.26上午地点工训楼C栋309 实验名称回溯法求旅行售货员问题实验目的通过上机实验,掌握回溯算法的思想,利用回溯法求旅行售货员问题并实现。实验原理旅行售货员问题的解空间树是一棵排列树。当i=n时,当前扩展结点是排列树的叶结点的父结点。此时算法检测图G是否存在一条从顶点xn-1到顶点xn的边和一条从顶点xn到顶点1的边。如果这两条边都存在,则找到一条旅行售货员回路。此时,算法还需要判断这条回路的费用是否优于已找到的当前最优回路的费用bestc。如

2、果是,则必须更新当前最优值bestc和当前最优解bestx。 当in时,当前扩展结点位于排列树的第i-1层。图G中存在从顶点xi-1到顶点xi的边时,x1:i构成图G的一条路径,且当x1:i的费用小于当前最优值时算法进入排列树的第i层,否则将减去相应的子树。算法中用变量cc记录当前路径x1:i的费用。 实验步骤1 从起点开始,找其子结点,即存在一条边相连。2 如果费用小于当前最优值则以此结点继续向下探索,否则就剪去相应的子树。3 当扩展到叶结点的父结点时,检测此结点与叶结点,叶结点与起点是否有边相连。4 若均有边相连,则检测此回路的费用是否小于最优费用。5 若小于最优费用,则更新最优费用,同时

3、记录最优解。关键代码/定义图的顶点数 const int N = 4; /*=定义Traveling类来存储的信息。=*/templateclass Traveling template friend T TSP(T *a, int n); private: void Backtrack(int i); int n, / 图G的顶点数 *x, / 当前解 *bestx; / 当前最优解 Type *a, / 图G的领接矩阵 cc, / 当前费用 bestc; / 当前最优值 int NoEdge; / 无边标记 ; /*=Backtrack函数为递归算法。 当i=n时,当前扩展结点是排列树的叶

4、结点的父结点。此时算法检测图G是否存在一条从顶点xn-1到顶点xn的边和一条从顶点xn到顶点1的边。如果这两条边都存在,则找到一条旅行售货员回路。此时,算法还需要判断这条回路的费用是否优于已找到的当前最优回路的费用bestc。如果是,则必须更新当前最优值bestc和当前最优解bestx。 当in时,当前扩展结点位于排列树的第i-1层。图G中存在从顶点xi-1到顶点xi的边时,x1:i构成图G的一条路径,且当x1:i的费用小于当前最优值时算法进入排列树的第i层,否则将减去相应的子树。算法中用变量cc记录当前路径x1:i的费用。 =*/ templatevoid Traveling:Backtra

5、ck(int i) /前扩展结点是排列树的叶结点的父结点 if (i = n) /检测是否存在一条从顶点xn-1到顶点xn的边和一条从顶点xn到顶点1的边 /存在且这条回路的费用小于已找到的最优费用 if (axn-1xn != 0 & axn1 != 0 & (cc + axn-1xn + axn1 bestc | bestc = 0) /记录最优解 for (int j = 1; j = n; j+) bestxj = xj; /更新最优费用 bestc = cc + axn-1xn + axn1; /前扩展结点位于排列树的第i-1层 else for (int j = i; j = n;

6、 j+) / 判断是否可进入xj子树 if (axi-1xj != 0 & (cc + axi-1xi bestc | bestc = 0) / 搜索子树 /交换 int temp=xi; xi=xj; xj=temp; /当前费用累加 cc += axi-1xi; /排列向右扩展,排列树向下一层扩展 Backtrack(i+1); /当前费用减少 cc -= axi-1xi; /交换 temp=xi; xi=xj; xj=temp; /*=TSP函数进行初始化,并返回最短路径的长度。主要为使用Backtrack函数进行搜索。 =*/templateType TSP(Type *a, int

7、n) /定义traveling类型的变量Y Traveling Y; /初始化Y Y.n=n; Y.x=new intn+1; Y.bestx=new intn+1; /置x为单位排列 for(int i=1;i=n;i+) Y.xi=i; Y.a=a; Y.cc=0; Y.bestc=0; Y.NoEdge=0; /搜索x2:n的全排列 Y.Backtrack(2); /输出最短回路 cout最短回路为:endl; for(int i=1;i=n;i+) coutY.bestxi ; coutY.bestx1endl; /删除动态内存分配 delete Y.x; Y.x=0; delete

8、Y.bestx; Y.bestx=0; return Y.bestc; /*= Swap函数实现两个数值交换。 需要注意的是形参那里一定要使用&符号,不然的话修改之后的结果不会在其他函数中看到。 =*/ template inline void Swap(Type &a, Type &b) Type temp=a; a=b; b=temp; 测试结果1. 使用的图如下所示:2. 相应的排列树如下所示:3. 至个叶结点的路径叶结点路径长度路径顺序L591-2-3-4-1M661-2-4-3-1N251-3-2-4-1O661-3-4-2-1P251-4-2-3-1Q591-4-3-2-14. 由

9、上表可以知道最短的为至叶结点Q的路径1-3-2-4-1,长度为25。这里可能会有疑问,至结点P的距离也为25,为什么不选择路径1-4-2-3-1。这是因为只有当求得的路径比当前最优值小的时候才会记录,这里一样大,所以不会记录,也就不会输出这条路径。5. 算法输出结果如下:6. 可以看到输出的结果与分析的结果一样,所以算法实现正确。并且可以看到分支限界法在实现我们给的这个图的时候,时间性能很好。实验心得因为我自己觉得解空间为排列树的问题的算法不是很好理解,所以就多编写了旅行售货员问题的代码,这里使用的是回溯法实现。就整体上来说,我认为回溯法的思想还是很好理解的,就是扩展一个结点的子结点,继续扩展

10、子结点的子结点,当不能扩展的时候,就返回到上一个扩展结点,找其他的子结点进行扩展,当往回找到根结点,根结点没有子结点继续扩展的时候,就结束算法。但是这里是排列树的回溯法,就难理解一点。主要是使用了交换。void backtrack (int t) if (tn) output(x); else for (int i=t;i=n;i+) swap(xt, xi); if (legal(t) backtrack(t+1); swap(xt, xi); 排列树的实现的伪代码如上所示。主要存在两个交换。第一个交换是保存xt当前的状态,而后面一个交换则是回到xt刚才的状态。理解了这一点之后,回溯法求解旅

11、行售货员问题的代码其实也就不难理解了。因为这里给的图的顶点比较少,无法直观的看出算法的时间性能。就回溯法求解旅行售货员问题,如果不考虑更新bestx所需的计算时间,则Backtrack需要O(n-1)!)计算时间。由于算法Backtrack在最坏情况下可能需要更新当前最优解 O(n-1)!)次,每次更新bestx需要O(n)计算时间,所以整个算法的计算时间复杂性为O(n!)。通过这次实验,编写了回溯法求解旅行售货员问题的代码,熟悉了回溯法求解问题的步骤,熟练掌握了回溯法,理解了排列树的问题,进一步熟悉了旅行售货员问题的问题描述与解题思路。相信在以后的学习工作中,一定可以熟练使用回溯法求解问题,

12、当然肯定可以使用回溯法求解旅行售货员问题。实验得分助教签名附录:完整代码#include #include#include#include#includeusing namespace std; /定义图的顶点数 const int N = 4; /*=定义Traveling类来存储的信息。=*/ templateclass Traveling template friend T TSP(T *a, int n); private: void Backtrack(int i); int n, / 图G的顶点数 *x, / 当前解 *bestx; / 当前最优解 Type *a, / 图G的领接

13、矩阵 cc, / 当前费用 bestc; / 当前最优值 int NoEdge; / 无边标记 ; /*=Backtrack函数为递归算法。 当i=n时,当前扩展结点是排列树的叶结点的父结点。此时算法检测图G是否存在一条从顶点xn-1到顶点xn的边和一条从顶点xn到顶点1的边。如果这两条边都存在,则找到一条旅行售货员回路。此时,算法还需要判断这条回路的费用是否优于已找到的当前最优回路的费用bestc。如果是,则必须更新当前最优值bestc和当前最优解bestx。 当in时,当前扩展结点位于排列树的第i-1层。图G中存在从顶点xi-1到顶点xi的边时,x1:i构成图G的一条路径,且当x1:i的费

14、用小于当前最优值时算法进入排列树的第i层,否则将减去相应的子树。算法中用变量cc记录当前路径x1:i的费用。 =*/ templatevoid Traveling:Backtrack(int i) /前扩展结点是排列树的叶结点的父结点 if (i = n) /检测是否存在一条从顶点xn-1到顶点xn的边和一条从顶点xn到顶点1的边 /存在且这条回路的费用小于已找到的最优费用 if (axn-1xn != 0 & axn1 != 0 & (cc + axn-1xn + axn1 bestc | bestc = 0) /记录最优解 for (int j = 1; j = n; j+) bestxj

15、 = xj; /更新最优费用 bestc = cc + axn-1xn + axn1; /前扩展结点位于排列树的第i-1层 else for (int j = i; j = n; j+) / 判断是否可进入xj子树 if (axi-1xj != 0 & (cc + axi-1xi bestc | bestc = 0) / 搜索子树 /交换 int temp=xi; xi=xj; xj=temp; /当前费用累加 cc += axi-1xi; /排列向右扩展,排列树向下一层扩展 Backtrack(i+1); /当前费用减少 cc -= axi-1xi; /交换 temp=xi; xi=xj;

16、xj=temp; /*=TSP函数进行初始化,并返回最短路径的长度。主要为使用Backtrack函数进行搜索。 =*/ templateType TSP(Type *a, int n) /定义traveling类型的变量Y Traveling Y; /初始化Y Y.n=n; Y.x=new intn+1; Y.bestx=new intn+1; /置x为单位排列 for(int i=1;i=n;i+) Y.xi=i; Y.a=a; Y.cc=0; Y.bestc=0; Y.NoEdge=0; /搜索x2:n的全排列 Y.Backtrack(2); /输出最短回路 cout最短回路为:endl;

17、 for(int i=1;i=n;i+) coutY.bestxi ; coutY.bestx1endl; /删除动态内存分配 delete Y.x; Y.x=0; delete Y.bestx; Y.bestx=0; return Y.bestc; /*= Swap函数实现两个数值交换。 需要注意的是形参那里一定要使用&符号,不然的话修改之后的结果不会在其他函数中看到。 =*/ template inline void Swap(Type &a, Type &b) Type temp=a; a=b; b=temp; /*=main函数是主函数。实现输入输出,调用之前的分支限界法函数Short

18、esPaths记录源到各顶点的最短路径长度。并且同时在prev数组中记录其前驱结点。 根据图的prev数组,求出最短路径。 从终点开始,之后到终点的前驱结点,直至找到起点为止,就找出了到终点的路径。 将找到的到终点的路径,存储在trave_pre数组中。 因为trave_pre数组中存储的为倒序的路径,所以反向输出即为路径。=*/ int main() cout=endl; cout=回溯法求TSP问题=endl; cout=endl; /输出图的顶点个数 cout图的顶点个数为Nendl; int bestlength; /动态内存分配 int *a=new int*N+1; for(int

19、 i=0;i=N;i+) ai=new intN+1; /初始化 for(int i=0;i=N;i+) for(int j=0;jN;j+) aij=0; a12=30;a13=6;a14=4; a21=30;a23=5;a24=10; a31=6;a32=5;a34=20; a41=4;a42=10;a43=20; /开始计时 clock_t start,end,over; start=clock(); end=clock(); over=end-start; start=clock(); /调用函数 bestlength=TSP(a,N); /结束计时 end=clock(); /输出最短回路的长度 cout最短回路的长为:bestlengthendl; /输出时间 printf(The time is %6.3fn,(double)(end-start-over)/CLK_TCK); /释放动态分配的内存 for(int i=0;i=N;i+) delete ai; delete a; return 0;

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

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