HDU 2224 The shortest path 双调旅行商有关问题
HDU 2224 The shortest path 双调旅行商问题
题目来源:HDU 2224 The shortest path
题意:求从1到n 然后在从n到1的最短路 去的时候经过的点的顺序必须从小到大 来的时候经过的点的顺序必须从大到小 并且每个点只能经过一次(1和n不算) 输出最短路的长度
思路:经典题 参考了大牛http://www.cppblog.com/doer-xee/archive/2009/11/30/102296.html
#include <cstdio> #include <cstring> #include <cmath> using namespace std; const int maxn = 210; double dp[maxn][maxn]; double d[maxn][maxn]; struct point { double x, y; }a[maxn]; double dis(int i, int j) { return sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)); } int main() { int n; while(scanf("%d", &n) != EOF) { for(int i = 1; i <= n; i++) scanf("%lf %lf", &a[i].x, &a[i].y); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { d[i][j] = dis(i, j); } } dp[1][2] = d[1][2]; for(int i = 3; i <= n; i++) { for(int j = 1; j < i-1; j++) dp[j][i] = dp[j][i-1] + d[i-1][i]; dp[i-1][i] = 999999999.0; for(int j = 1; j < i-1; j++) { double sum = dp[j][i-1] + d[j][i]; if(dp[i-1][i] > sum) dp[i-1][i] = sum; } } dp[n][n] = dp[n-1][n] + d[n-1][n]; printf("%.2f\n", dp[n][n]); } return 0; }