【Jason's_ACM_解题报告】Tour

Tour

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.


Input 
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.


Output 
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).


Sample Input 

1 1
2 3
3 1

1 1 
2 3
3 1
4 2


Sample Output 
6.47
7.89

这道题是一道经典问题,为双调欧几里德旅行商问题。

双调路径:从最左点开始,严格的从左到右直至最右点,然后严格的从右到左,直至出发点,其中,两路线除了起始点意外,不允许有任何重复的点。这就是双调路线。


此题通过时间复杂度为O(N^2)的动态规划解决方法解决。

为简便起见,我们设两路径均为从最左点开始,直至最右点。我们定义dp[i][j]为两路线现在一个到达了i点、另一个到达了j点,其中i>j。

那么对于状态dp[i][j],我们有两种行走方式,一种是由i行走之i+1,另一种是由j行走至i+1,此处应留意i>j,且行至i+1所获得的答案会比行至i+k(k>1)所获得的答案更优。

从而获得状态转移方程:

1. dp[i][j]=dp[i+1][j]+dist[i][i+1];

2. dp[i][j]=dp[i+1][i]+dist[j][j+1];


最后边界为两路线汇聚在点n,所以dp[n-1][j]=dist[n-1][n]+dist[j][n];。

答案为dp[1][1]=dp[2][1]+dist[1][2];


至此,题目得以解决。


附代码如下:
#include<cmath>
#include<cstdio> 

#include<algorithm>

using namespace std;

#define MAXN (50+5)

struct NODE{
	double x,y;
	bool operator < (const NODE& rhs) const {return x<rhs.x;}
};

int n;
NODE a[MAXN];
double dist[MAXN][MAXN],dp[MAXN][MAXN];

double dkj(int i,int j){
	double x1=a[i].x,x2=a[j].x;
	double y1=a[i].y,y2=a[j].y;
	return sqrt(pow(x1-x2,2)+pow(y1-y2,2));
}

int main(){
	while(scanf("%d",&n)!=EOF){
		for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
		sort(a+1,a+n+1);
		
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i!=j)dist[i][j]=dkj(i,j);
			}
		}
		
		for(int i=n-1;i>=2;i--){
			for(int j=1;j<i;j++){
				if(i==n-1){dp[i][j]=dist[i][n]+dist[j][n];}
				else{
					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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值