UVA1347 Tour

来源:互联网 发布:高斯金字塔 源码 编辑:程序博客网 时间:2024/05/21 17:31

一. Vjudge链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=38898

二. 题目大意:给你一个二维坐标系上的若干个点,让你从一个点出发,走遍所有的点,并回到当前点,2个点的距离就是其欧几里得距离(初中平面2点距离公式)。求最短的路径。题目的横坐标由小到大依次给出。

三. 思路:(来自紫书)可以把问题转化为:2个人从最左边的点开始走,(除了起点和终点)每个点恰好被2个人其中一个走过。最终2个人一起走到第n个点。

定义dp[i][j]为一个人在第i个点,另一个人在第j个点时离终点n的距离,并且i>j,而且第i个点之前的点全部被走过(意味着每次只能走到i+1个点)。于是我们可以得出,在前n-1个点全部都被走过之后,最后一步肯定是2个人都走向第n个点,也就是开始条件dp[n-1][j] = dist(n-1, n) + dist(j. n),dist表示2个点之间的距离,这是开始条件,因为我们定义的dp[][]是到达终点的距离,然后要转移到前一个状态只要dp[i][j] = min(dp[i+1][j] + dist(i, i+1), dp[i+1][i]+dist(j, i+1)),表示在i位置的人走到i+1或者在j位置的人走到i+1。最后只要dp[2][1]+dist(1,2)就行了。

四. 代码(非递归)

#include <iostream>#include <cstdio>#include <queue>#include <cstring>#include <cmath>#include <algorithm>using namespace std;const int MAX_N = 1024,          INF = 0x3f3f3f3f;//dp[i][j] 表示第一个人走到第i个点,第二个人走到第j个点,并且i>j,前i个点全部走过,此时离第n个点的距离。double dp[MAX_N][MAX_N],       x[MAX_N], y[MAX_N];int n;double dist(int i, int j){    return sqrt((x[i]-x[j])*(x[i]-x[j]) +                (y[i]-y[j])*(y[i]-y[j]));}int main(){    //freopen("in.txt", "r", stdin);    int i, j;    while(~scanf("%d", &n)){        for(i = 1; i <= n; i++)            scanf("%lf %lf", x+i, y+i);        for(j = 1; j < n-1; j++)            dp[n-1][j] = dist(n-1, n) + dist(n, j);        for(i = n-2; i >= 1; i--)            for(j = 1; j < i; j++)                dp[i][j] = min(dp[i+1][j] + dist(i, i + 1),                               dp[i+1][i] + dist(j, i + 1));        printf("%.2lf\n", dp[2][1] + dist(1, 2));    }    return 0;}


0 0