• 【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 == '
    ');
    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
    ", dp[n][n]);
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    1755:菲波那契数列
    1788:Pell数列
    3089:爬楼梯
    7832:最接近的分数
    7649:我家的门牌号
    7216:Minecraft
    7213:垃圾炸弹
    2983:谁是你的潜在朋友
    2723:因子问题
    2722:和数
  • 原文地址:https://www.cnblogs.com/Destiny-Gem/p/4063378.html
Copyright © 2020-2023  润新知