欧几里得旅行商问题

ぐ巨炮叔叔 提交于 2020-01-24 10:14:53

注:本文转载自网络,笔者略有改动,感谢作者整理。     

欧几里得旅行商问题,又叫货郎问题(Traveling Salesman Problem,简称“TSP”)也叫货郎担问题,中国邮路问题,旅行商问题等,是计算机算法理论历史上的经典问题。在过去几十年中,它成为许多重要算法思想的测试平台,同时也促使一些新的理论领域的产生,比如多面体理论和复杂性理论。 货郎问题:给定n个结点和任意一对结点{i,j}之间的距离为dist(i,j),要求找出一条闭合的回路,该回路经过每个结点一次且仅一次,并且该回路的费用最小,这里的费用是指每段路径的距离和。 货郎问题求解其精确解是NP难的,并且求解任意常数因子近以度的解也是NP难的。若将问题限定在欧氏平面上,就成为欧氏平面上的货郎问题,也叫欧几里德旅行商问题(Eculid Traveling Salesman Problem)。但是,即使是欧氏平面上的货郎问题也是NP难的。因此通常用来解决TSP问题的解法都是近似算法。其中第一个欧几里德旅行商问题的多项式近似算法是Arora在1996年使用随机平面分割和动态规划方法给出的。


    J.L. Bentley 建议通过只考虑双调旅程(bitonic tour)来简化问题,这种旅程即为从最左点开始,严格地从左到右直至最右点,然后严格地从右到左直至出发点。事实上,存在确定的最优双调路线的O(n*n)时间的算法。

 1 /**********************************************************************
 2 *        Bitonic path (详见《算法导论》 P217)                                                                                   
 3 *        一个人从p1严格地增的走到pn,然后再严格递减的回到p1;求总路径的最小值;    6 *        对于1 <= i <= j <= n, 我们定义P(i, j)是一条包含了P1, P2, P3 …… Pj的途径;                   
 7 *        这条路径可以分成2部分:递减序列与递增序列                                                                
 8 *        起点是Pi(1 <= i <= j),拐点是P1,终点是Pj, P[i, j]为其最小值;                                     
 9 *        状态转移方程为:                                                                                                                      
10 *        b[1,2] = |P1P2|,                                                                                                                               
11 *        i < j-1时, b[i,j] = b[i,j-1] + |Pj-1Pj|    点Pj-1在递增序列中,   *                   因为要求P(i,j)要求i<=j,所以在此种情况下新的节点是加在递增序列部分的                                                
12 *        i = j-1时, b[i,j] = min{ b[k,j-1] + |PkPj|, 1<= k < j-1 }   *                           = min{b[k,i]+|PkPj|,1<=k<j-1}  点Pj-1在递减序列中                 
13 *        b[n,n] = b[n-1,n] + |Pn-1Pn|                                                                                                         
14 **********************************************************************/
15 
16 
17 #include <stdio.h>
18 #include <math.h>
19 #define INF 0x7fffffff
20 #define N 201
21 struct point{
22     double x, y;
23 }point[N];
24 int n;
25 double dis[N][N];
26 
27 double distant(int i, int j)
28 {
29     return sqrt((point[i].x - point[j].x)*(point[i].x - point[j].x) + (point[i].y - point[j].y)*(point[i].y - point[j].y));
30 }
31 
32 double dp()
33 {
34     int i, j, k;
35     double temp, b[N][N];
36 
37     b[1][2] = dis[1][2];
38     for (j=3; j<=n; j++)
39     {
40         for (i=1; i<=j-2; i++)
41             b[i][j] = b[i][j-1] + dis[j-1][j];
42 
43         b[j-1][j] = INF;
44         for (k=1; k<=j-2; k++)
45         {
46             temp = b[k][j-1] + dis[k][j];
47             if (temp < b[j-1][j])
48                 b[j-1][j] = temp;
49         }
50     }
51 
52     b[n][n] = b[n-1][n] + dis[n-1][n];
53 
54     return b[n][n];
55 }
56 
57 int main()
58 {
59     int i, j;
60     double ans;
61     while (scanf("%d", &n) > 0)
62     {
63         for (i=1; i<=n; i++)
64             scanf("%lf %lf", &point[i].x, &point[i].y);
65 
66         for (j=2; j<=n; j++)
67             for (i=1; i<j; i++)
68                 dis[i][j] = distant(i,j); 
69 
70         ans = dp();
71 
72         printf("%.2lf\n", dp());
73     }
74 }

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!