双调欧几里得旅行商问题解法 (POJ 2677)

对于这个解法,网上题解一大堆。不过觉得还是算导官方给的解答好些,简洁又清楚。。。

 

大概总结一下(不是翻译)=.=

 首先是排序。

然后确定状态 f[i][j] (i >= j, i == j表示的只有n这个点) 表示 从i到1严格从右往左走然后再从1严格从左往右走到j 这样两条路径的最小值,当然[1, max(i, j)]区间上所有的点都是被访问过得。

存在两种状态 :

1:  j < i - 1;

dp[i][j] = dp[i-1][j] + Dis(i, i - 1);

2: j == i - 1;

dp[i][j] = min{dp[i][j], dp[j][k] + Dis(k, i)}  //这个dp[j][k]本来应该是dp[k][j]的,但是由于dp[x][y] = dp[y][x]所以用dp[j][k]表示更方便,因为dp[i][j]满足i > j, dp[j][k]也满足j > k。 

 

 POJ 2677&&HDU 2224代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cmath>
 4 #include <vector>
 5 #include <cstring>
 6 #include <algorithm>
 7 #include <string>
 8 #include <set>
 9 #include <ctime>
10 #include <queue>
11 #include <map>
12 #include <functional>
13 #include <numeric>
14 #include <sstream>
15 #include <stack>
16 
17 #define CL(arr, val)    memset(arr, val, sizeof(arr))
18 #define REP(i, n)       for((i) = 0; (i) < (n); ++(i))
19 #define FOR(i, l, h)    for((i) = (l); (i) <= (h); ++(i))
20 #define FORD(i, h, l)   for((i) = (h); (i) >= (l); --(i))
21 #define L(x)    (x) << 1
22 #define R(x)    (x) << 1 | 1
23 #define MID(l, r)   (l + r) >> 1
24 #define Min(x, y)   x < y ? x : y
25 #define Max(x, y)   x < y ? y : x
26 #define E(x)    (1 << (x))
27 #define iabs(x) (x) < 0 ? -(x) : (x)
28 #define OUT(x)  printf("%I64d\n", x)
29 #define lowbit(x)   (x)&(-x)
30 #define Read()    freopen("data.in", "r", stdin)
31 #define Write()   fropen("data.out", "w", stdout);
32 
33 const int eps = 1e-8;
34 typedef long long LL;
35 const double inf = 1e15;
36 
37 using namespace std;
38 
39 const int N = 1024;
40 
41 double f[N][N];
42 double dis[N][N];
43 
44 struct node {
45     int x;
46     int y;
47     bool operator < (const node cmp) const {
48         return x == cmp.x ? y < cmp.y : x < cmp.x;
49     }
50 }p[N];
51 
52 double Dis(int i, int j) {
53     return sqrt((p[i].x - p[j].x)*(p[i].x - p[j].x)*1. + (p[i].y - p[j].y)*(p[i].y - p[j].y)*1.);
54 }
55 
56 int main() {
57 //    Read();
58     int n, i, j, k;
59     double ans;
60     while(~scanf("%d", &n)) {
61         for(i = 1; i <= n; ++i) scanf("%d%d", &p[i].x, &p[i].y);
62         sort(p + 1, p + n + 1);
63         for(i = 1; i <= n; ++i) {
64             for(j = 1; j <= i; ++j)  {
65                 dis[i][j] = dis[j][i] = Dis(i, j);
66             }
67         }
68         f[2][1] = dis[2][1];
69         //i >= j
70         for(i = 3; i <= n; ++i) {
71             //j < i - 1
72             for(j = 1; j < i - 1; ++j)  f[i][j] = f[i-1][j] + dis[i-1][i];
73             //j == i - 1
74             j = i - 1;
75             f[i][j] = inf;
76             for(k = 1; k < j; ++k) {
77                 f[i][j] = min(f[i][j], f[j][k] + dis[k][i]);    //note: f[x][y] = f[y][x]
78             }
79         }
80 
81         if(n == 2)  ans = f[2][1];
82         else    ans = f[n][n-1] + dis[n][n-1];
83         printf("%.2f\n", ans);
84     }
85     return 0;
86 }

 

 

 

posted @ 2012-09-15 16:16  AC_Von  阅读(1512)  评论(1编辑  收藏  举报