zoukankan      html  css  js  c++  java
  • 双调欧几里得旅行商问题解法 (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 }
  • 相关阅读:
    010906侯舒舒(作业信息收集笔记)
    010806侯舒舒(作业信息收集)
    011106侯舒舒(作业计算机基础)
    011006侯舒舒(作业大型扫描)
    011006侯舒舒(日报)
    011106侯舒舒(日报)
    010906侯舒舒(日报)
    010606侯舒舒(作业基础)
    010706侯舒舒(作业漏洞测试)
    信息收集总结(慢慢扩充)
  • 原文地址:https://www.cnblogs.com/vongang/p/2686576.html
Copyright © 2011-2022 走看看