UVA 1347 Tour (Travel (Introduction to Algorithm Competition Classics - Example 9-3)) (translation, detailed explanation)

Tour

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

Given the coordinates of n (n<=1000) points on the plane (given in increasing order of x. The x-coordinates of each point are different and are all positive integers), your task is to design a route, starting from the leftmost point Start, go to the rightmost point and then return, requiring that each point except the leftmost and rightmost points pass exactly once, and the total length of the path is the shortest. The length between two points is their Euclidean distance (in this case, the distance between two points in two-dimensional space), as shown in the figure:


Input

The program input is from a text file. Each data set in the file stands for a particular set of points. Foreach set of points the data set contains the number of points, and the point coordinates in ascendingorder 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 beginningof 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 onecontains 3 points specified by their x and y coordinates. The second point, for example, has the xcoordinate 2, and the y coordinate 3. The result for each data set is the tour length, (6.47 for the firstdata set in the given example).

Sample Input

3

1 1

2 3

3 1

4

1 1

2 3

3 1

4 2

Sample Output

6.47

7.89

Ideas:

   "From left to right and back again" is not very convenient to think about. It can be changed to: two people start from the leftmost point at the same time, walk along two different paths, and finally reach the rightmost point, and the rest except the starting point and the end point Each point is passed by exactly one person. In this way, dp[i][j] can be used to indicate the distance the first person needs to walk to i and the second person to j.

     How does the state transfer? After thinking about it carefully, you will find that it seems difficult to guarantee that two people will not come to the same point. For example, when calculating state d[i][j], can i go to i+1? I don't know, because it can't be seen from the state whether i+1 has been passed by j. In other words, the state is poorly defined, leading to difficult transitions.

     Modify it as follows: dp[i][j] indicates that 1~max(i,j) have all walked, and the current positions of the two people are i and j respectively, and how long they need to travel. It is not difficult to find that dp[i][j]=dp[j][i], so it is stipulated that i>j in the state from now on. In this way, no matter who it is, the next step can only go to i+1, i+2,... these points. However, if you go to i+2, the situation becomes "1~i and i+2, but i+1 has not passed", which cannot be expressed as a state! How to do? Forbid this kind of decision! That is to say, only one of them is allowed to go to i+1 (and there must be one person to go to i+1, so as not to leak the solution) , but not to i+2,i+3,... . In other words, state dp[i][j] can only be transferred to dp[i+1][j] (the first person goes to i+1) or dp[i+1][i] ( the second person When reaching i+1, it should be transferred to dp[i][i+1], but according to the regulations here (i>j in the specified state dp[i][j]), it must be written as d[i+1][ i] ).

      However, this raises a question, is it possible that the above-mentioned "overbearing" provisions might be leaked? Will not. Because if the first person goes directly to i+2, then it can no longer go to i+1, and can only rely on the second person to go to i+1. In this case, let the second person go to i+1 now without losing the solution (that is, one person must go to the next step i+1).

       The boundary is d[n-1][j]=dis[n-1][n]+dis[j,n] , where dis[a][b] represents the distance between point a and point b. Because by definition, all points have been passed, two people just have to go straight to the end. The desired result is dis[1][2]+dp[2][1] , because the first step is that someone goes to the second point, which by definition is dp[2][1].

       The total number of states has O(n^2) decisions and each state has only two decisions, so the total time complexity is O(n^2).

AC code:

Recursive writing:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
double dp[1005][1005];//dp[i][j] indicates that the current positions of the two people are i, j respectively, and the minimum distance they need to travel, and set i>j, indicating the point before i all gone
int n;
struct node
{
	double x,y;
}map[1005];

double dis(int i,int j)//Find the distance between points i and j
{
	return sqrt((map[i].x-map[j].x)*(map[i].x-map[j].x)+(map[i].y-map[j].y)*(map[i].y-map[j].y));
}

intmain()
{
	while(~scanf("%d",&n))
	{
		for(int i=1;i<=n;i++)
		  scanf("%lf %lf",&map[i].x,&map[i].y);
		for(int i=1;i<=n-1;i++)
		  dp[n-1][i]=dis(n-1,n)+dis(i,n);
		for(int i=n-2;i>1;i--)
          for(int j=1;j<i;j++)//保证i>j       
          dp[i][j]=min(dp[i+1][j]+dis(i,i+1),dp[i+1][i]+dis(i+1,j));  
		printf("%.2lf\n",dis(1,2)+dp[2][1]);
	}
	return 0;
}

Recursive writing:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#define INF 0x3f3f3f3f
using namespace std;
double dp[1005][1005];//dp[i][j] indicates that the current positions of the two people are i, j respectively, and the minimum distance they need to travel, and i>j, the points before i have passed span
int n;
struct node
{
	double x,y;
}map[1005];

double dis(int i,int j)//Find the distance between points i and j
{
	return sqrt((map[i].x-map[j].x)*(map[i].x-map[j].x)+(map[i].y-map[j].y)*(map[i].y-map[j].y));
}

double getdp(int i,int j)
{
	if(dp[i][j]>0) return dp[i][j];
	return dp[i][j]=min(dis(i,i+1)+getdp(i+1,j),dis(j,i+1)+getdp(i+1,i));
}

intmain()
{
	while(~scanf("%d",&n))
	{
		memset(dp,0,sizeof(dp));
		for(int i=1;i<=n;i++)
		  scanf("%lf %lf",&map[i].x,&map[i].y);
		for(int i=1;i<=n-1;i++)
		  dp[n-1][i]=dis(n-1,n)+dis(i,n);
		printf("%.2lf\n",getdp(1,1));
		//printf("%.2lf\n",dis(1,2)+getdp(2,1));
	}
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324538563&siteId=291194637