【HDU2224】The shortest path(双调欧几里得dp)

算法导论上一道dp,挺有趣的。于是就研究了一阵。

dp(i, j)代表从左边第一个点到第i个点与从从左边最后一个点(即为第一个点)到j点的最优距离和。于是找到了子状态。

决策过程 dp[i][j] = min{dp[i-1][j] + Dis(i, i - 1), dp[i - 1][k] + Dis(k, i)} 即可。代表意思是选择最优的路径加入到回路中的去途或者归途中。

一下是代码。

 

 1 /****************************************/
 2 /*****            Desgard_Duan        *****/
 3 /****************************************/
 4 //#pragma comment(linker, "/STACK:102400000,102400000")
 5 #define _CRT_SECURE_NO_WARNINGS
 6 #include <iostream>
 7 #include <cstdio>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <string>
11 #include <algorithm>
12 #include <stack>
13 #include <map>
14 #include <queue>
15 #include <vector>
16 #include <set>
17 #include <functional>
18 #include <cmath>
19 #include <numeric>
20 #include <limits.h>
21 
22 using namespace std;
23 
24 inline void get_val(int &a) {
25     int value = 0, s = 1;
26     char c;
27     while ((c = getchar()) == ' ' || c == '\n');
28     if (c == '-') s = -s; else value = c - 48;
29     while ((c = getchar()) >= '0' && c <= '9')
30         value = value * 10 + c - 48;
31     a = s * value;
32 }
33 
34 vector<pair<double, double> > P;
35 int n;
36 double x, y, dis[205][205], dp[205][205];
37 
38 double caldis (double x1, double y1, double x2, double y2) {
39     return sqrt ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
40 }
41 
42 int main () {
43     while (~scanf ("%d", &n)) {
44         P.clear();
45         memset (dis, 0, sizeof (dis));
46         memset (dp , 0, sizeof (dp));
47         for (int i = 0; i < n; ++ i) {
48             scanf ("%lf %lf", &x, &y);
49             P.push_back (make_pair(x, y));
50         }
51         for (int i = 0; i < P.size(); ++ i) {
52             for (int j = 0; j < P.size(); ++ j) {
53                 dis[i + 1][j + 1] = dis[j + 1][i + 1]
54                     = caldis (P[i].first, P[i].second, P[j].first, P[j].second);
55             }
56         }
57 
58         dp[1][2] = dis[1][2];
59         //cout << dp[1][2] << endl;
60         for (int j = 3; j <= n; ++ j) {
61             for (int i = 1; i <= j - 2; ++ i) {
62                 dp[i][j] = dp[i][j - 1] + dis[j - 1][j];
63             }
64 
65             dp[j - 1][j] = UINT_MAX;
66 
67             for (int k = 1; k <= j - 2; ++ k) {
68                 dp[j - 1][j] = min (dp[j - 1][j], dp[k][j - 1] + dis[k][j]);
69             }
70         }
71         dp[n][n] = dp[n - 1][n] + dis[n - 1][n];
72         printf ("%.2lf\n", dp[n][n]);
73     }
74     return 0;
75 }

 

posted @ 2014-10-30 18:22  Desgard_Duan  阅读(592)  评论(0编辑  收藏  举报