【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 }

 

你可能感兴趣的:(Path)