码迷,mamicode.com
首页 > 编程语言 > 详细

UVa 1347 (双线程DP) Tour

时间:2014-09-29 01:02:16      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   io   os   ar   for   sp   

题意:

平面上有n个坐标均为正数的点,按照x坐标从小到大一次给出。求一条最短路线,从最左边的点出发到最右边的点,再回到最左边的点。除了第一个和最右一个点其他点恰好只经过一次。

分析:

可以等效为两个人从第一个点出发,沿不同的路径走到最右点。

d(I, j)表示点1~max(I, j)这些点全部都走过,而且两人的位置分别是i和j,最少还需要走多长的距离。由这个定义可知,d(I, j) == d(j, i),所以我们再加一个条件,d(I, j)中i>j

这样状态d(I, j)只能转移到d(i+1, j)和d(i+1, i)

边界:d(n-1, j) = dist(n-1, n) + dist(j, n) (1 ≤ j < n-1)

最终所求答案就是dist(1, 2) + d(1, 2)

 

bubuko.com,布布扣
 1 //#define LOCAL
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 
 8 const int maxn = 1000 + 10;
 9 double x[maxn], y[maxn], dp[maxn][maxn], dis[maxn][maxn];
10 
11 double dist(int a, int b)
12 {
13     return sqrt((double)(x[a]-x[b])*(x[a]-x[b]) + (y[a]-y[b])*(y[a]-y[b]));
14 }
15 
16 int main(void)
17 {
18     #ifdef LOCAL
19         freopen("1347in.txt", "r", stdin);
20     #endif
21 
22     int n;
23     while(scanf("%d", &n) == 1)
24     {
25         for(int i = 1; i <= n; ++i)    scanf("%lf%lf", &x[i], &y[i]);
26         for(int i = 2; i <= n; ++i)
27             for(int j = 1; j < i; ++j)
28                 dis[i][j] = dis[j][i] = dist(i, j);
29         for(int i = n - 1; i > 1; --i)
30             for(int j = 1; j < i; ++j)
31             {
32                 if(i == n - 1)    dp[i][j] = dis[j][n] + dis[i][n];
33                 else dp[i][j] = min(dp[i+1][j] + dis[i][i+1], dp[i+1][i] + dis[i+1][j]);
34             }
35         printf("%.2lf\n", dis[1][2] + dp[2][1]);
36     }
37 
38     return 0;
39 }
代码君

 

UVa 1347 (双线程DP) Tour

标签:style   blog   http   color   io   os   ar   for   sp   

原文地址:http://www.cnblogs.com/AOQNRMGYXLMV/p/3999175.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!