1、TSP 问题算法实验报告指导教师: 季晓慧 姓 名: 辛瑞乾 学 号: 1004131114 提交日期: 2015 年 11 月 目录总述 .2动态规划法 .2算法问题分析 .2算法设计 .2实现代码 .2输入输出截图 .5OJ 提交截图 5算法优化分析 .5回溯法 .5算法问题分析 .5算法设计 .6实现代码 .6输入输出截图 .8OJ 提交截图 8算法优化分析 .9分支限界法 .9算法问题分析 .9算法设计 .9实现代码 .9输入输出截图 .14OJ 提交截图 14算法优化分析 .14总结 .15总述TSP 问题又称为旅行商问题,是指一个旅行商要历经所有城市一次最后又回到原来的城市,求最短
2、路程或最小花费,解决 TSP 可以用好多算法,比如蛮力法,动态规划法具体的时间复杂的也各有差异,本次实验报告包含动态规划法,回溯法以及分支限界法。动态规划法算法问题分析假设 n 个顶点分别用 0n-1 的数字编号,顶点之间的代价存放在数组 mpnn中,下面考虑从顶点 0 出发求解 TSP 问题的填表形式。首先,按个数为 1、2、n-1 的顺序生成1n-1 个元素的子集存放在数组 x2n-1中,例如当 n=4 时,x1=1,x2=2,x3=3,x4=1,2,x5=1,3,x6=2,3,x7=1,2,3。设数组 dpn2n-1存放迭代结果,其中 dpij表示从顶点 i 经过子集 xj中的顶点一次且
3、一次,最后回到出发点 0 的最短路径长度,动态规划法求解 TSP 问题的算法如下。算法设计输入:图的代价矩阵 mpnn输出:从顶点 0 出发经过所有顶点一次且仅一次再回到顶点 0 的最短路径长度1. 初始化第 0 列(动态规划的边界问题)for(i=1;i#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #
4、include #define debug “output for debugn“#define pi (acos(-1.0)#define eps (1e-8)#define inf 0x3f3f3f3f#define ll long long int#define lson l , m , rt 0)x=dpk(j-(1=1)3.1、 xk=xk+1,搜索下一个顶点。3.2、若 n 个顶点没有被穷举完,则执行下列操作3.2.1、若顶点 xk不在湖密顿回路上并且 (xk-1,xk)E ,转步骤 3.3;3.2.2、否则,xk=xk+1,搜索下一个顶点。3.3、若数组 xn已经形成哈密顿路径,
5、则输出数组 xn,算法结束;3.4、若数组 xn构成哈密顿路径的部分解,则 k=k+1,转步骤 3;3.5、否则,取消顶点 xk的访问标志,重置 xk,k=k-1,转步骤 3。实现代码#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define debug “outp
6、ut for debugn“#define pi (acos(-1.0)#define eps (1e-8)#define inf 0x3f3f3f3f#define ll long long int#define lson l , m , rt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #incl
7、ude #define debug “output for debugn“#define pi (acos(-1.0)#define eps (1e-8)#define inf 0x3f3f3f3f#define ll long long int#define lson l , m , rt Mp20;vector:iterator it;int mp2020;int vis20;int up,low,n,ans;struct nodeint x20,st,ed,dis,val,num;bool operatorq;int getup(int u,int v,int w)if(v=n) ret
8、urn w+mpu1;int sum=inf,p;for(int i=1; impui)sum=mpui;p=i;visp=1;return getup(p,v+1,w+sum);int getlow()int sum=0;for(int i=1; i=n; i+)it=Mpi.begin();sum+=*it;it+;sum+=*it;return sum/2;int gao(node s)int res=s.dis*2;int t1=inf,t2=inf;for(int i=1; i=n; i+)if(!s.xi)t1=min(t1,mpis.st);t2=min(t2,mps.edi);
9、res+=t1;res+=t2;int tmp;for(int i=1; i=n; i+)tmp=inf;if(!s.xi)it=Mpi.begin();res+=*it;for(int j=1; j=n; j+)tmp=min(tmp,mpji);res+=tmp;return !(res%2) ? (res/2):(res/2+1);void bfs(node s)q.push(s);while(!q.empty()node head=q.top();q.pop();if(head.num=n-1)int p;for(int i=1; i=n; i+)if(!head.xi)p=i;bre
10、ak;int cnt=head.dis+mpphead.st+mphead.edp;node tmp=q.top();if(cnt=tmp.val)ans=min(ans,cnt);return;elseup=min(up,cnt);ans=min(ans,cnt);continue;node tmp;for(int i=1; i=n; i+)if(!head.xi)tmp.st=head.st;tmp.dis=head.dis+mphead.edi;tmp.ed=i;tmp.num=head.num+1;for(int j=1; j=n; j+) tmp.xj=head.xj;tmp.xi=
11、1;tmp.val=gao(tmp);if(tmp.val=up)q.push(tmp);int main()while(scanf(“%d“, i=n; i+)Mpi.clear();for(int i=1; i=n; i+)for(int j=1; j=n; j+)if(i!=j)scanf(“%d“,Mpi.push_back(mpij);elsempij=inf;sort(Mpi.begin(),Mpi.end();memset(vis,0,sizeof vis);vis1=1;up=0;up+=getup(1,1,up);low=getlow();node fir;fir.st=1;
12、fir.ed=1;fir.num=1;for(int i=1; i=n; i+) fir.xi=0;fir.x1=1;fir.dis=0;fir.val=low;ans=inf;bfs(fir);printf(“%dn“,ans);return 0;输入输出截图OJ 提交截图算法优化分析分支限界法的复杂度是根据数据的不同而不同,搜索的节点越少,复杂度越低,跟目标函数的选择有很大关系。目标函数值的计算也会需要一定时间,比如此文章中的目标函数值求解的复杂度是 O(n2 )。当然此算法仍然有可以优化的地方,比如在记录该路径每个叶子结点的孩子结点时可以采用二进制的思想,从而使算法的时间复杂度在下降到当前T/n 的数量级,解决 COJ1814 问题应该不成问题。总结TSP 问题在很多地方都可以运用到,并且好多问题都是由 TSP 问题延伸和发展的,也可以称之为 TSP 问题,不过其思路大致相似,于是我们可以运用已学过的算法对其进行解决。我在学习算法课以前的 TSP 问题大都用动态规划以及回溯法,究其时间复杂度以及代码的复杂度比较低,思路比较清晰,在解决此类延伸问题时容易调试和修改。学完算法后最有感触的一点就是,算法的精髓并不在于其方式方法,而在于其思想思路。有了算法的思想,那么潜移默化中问题就可以得到解决。