算法导论上一道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 }