codeforce_exercise_r7

Tour (UVa-1347) :

问题描述

题目简述

John Doe, a skilled pilot, enjoys traveling. While on vacation, he rents a small plane and starts visiting
beautiful places. To save money, John must determine the shortest closed tour that connects his
destinations. Each destination is represented by a point in the plane pi =< xi, yi >. John uses the
following strategy: he starts from the leftmost point, then he goes strictly left to right to the rightmost
point, and then he goes strictly right back to the starting point. It is known that the points have
distinct x-coordinates.
Write a program that, given a set of n points in the plane, computes the shortest closed tour that
connects the points according to John’s strategy.

输入/输出格式

输入格式:
The program input is from a text file. Each data set in the file stands for a particular set of points. For
each set of points the data set contains the number of points, and the point coordinates in ascending
order of the x coordinate. White spaces can occur freely in input. The input data are correct.

输出格式:
For each set of data, your program should print the result to the standard output from the beginning
of a line. The tour length, a floating-point number with two fractional digits, represents the result.
Note: An input/output sample is in the table below. Here there are two data sets. The first one
contains 3 points specified by their x and y coordinates. The second point, for example, has the x
coordinate 2, and the y coordinate 3. The result for each data set is the tour length, (6.47 for the first
data set in the given example).

样例

输入样例:
3
1 1
2 3
3 1
4
1 1
2 3
3 1
4 2
输出样例:
6.47
7.89

问题分析

解题思路

从起点走到终点再走回来,每个点都走一遍,这个过程直接想的话比较复杂,但是可以将其看成是两个人,都从起点出发,沿不同的路线走到终点,并且两者的路径上的点没有重复。因此,可以定义dp(i,j)为第一个人在i点,第二个人在j点,并且1-max(i,j)均已经走过一遍的状态。同时可以规定i>j因为dp(i,j)和dp(j,i)是相同的。在决策时,只需要考虑从i点迁移到i+1点即可(这样不会漏解,因为dp(i+n,j)这个状态包含了另一个人已经走完了i+1到i+n-1这些结点)。这样在决策时,就有两种情况:
1.第一个人走到i+1:dp(i+1,j)=dp(i,j)+dist(i+1,i)
2.第二个人走到i+1:dp(i+1,i)=dp(i,j)+dist(i+1,j)

参考代码
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>

using namespace std;

class point
{
public:
	int x,y;
	point(int xx,int yy)
	{
		x=xx;
		y=yy;
	}
	point()
	{}
};

point points[1010];
int n;
double dp[1010][1010];

void init()
{
	memset(dp,0,sizeof(dp));
	memset(points,0,sizeof(points));
}

double dist(int id1,int id2)
{
	double d;
	d=sqrt((points[id1].x-points[id2].x)*(points[id1].x-points[id2].x)+(points[id1].y-points[id2].y)*(points[id1].y-points[id2].y));
	return d;
} 

int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		init();
		for(int i=1;i<=n;i++)
		{
			int xx,yy;
			scanf("%d %d",&xx,&yy);
			points[i].x=xx;
			points[i].y=yy;
		} 
		dp[2][1]=dist(2,1);
		for(int i=2;i<n;i++)
		{
		    for(int j=1;j<i;j++)
		    {
		    	if(dp[i+1][j]==0||dp[i+1][j]>dp[i][j]+dist(i,i+1))
		    	{
		    		dp[i+1][j]=dp[i][j]+dist(i,i+1);
				}
				if(dp[i+1][i]==0||dp[i+1][i]>dp[i][j]+dist(j,i+1))
				{
					dp[i+1][i]=dp[i][j]+dist(j,i+1);
				}
			}
		}
		double re=0;
		for(int i=1;i<n;i++) 
		{
            if(re==0||re>dp[n][i]+dist(i,n))
                re=dp[n][i]+dist(i,n);
        }
        printf("%.2lf\n",re);
	}
	return 0;
}

心得体会

我自己是没想到dp的状态还可以这样定义,看了书上的解析,其实也没看太明白,想了很久,才想明白这个定义是啥意思。确实不太好做。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值