ural 1143. Electric Path
1143. Electric Path
Time limit: 1.0 second
Memory limit: 64 MB
Memory limit: 64 MB
Background
At the team competition of the 10th national student informatics Olympic, which is organized at Hanoi National University, there are N teams participating. Each team is assigned to work in a camp. On the map, it can be seen that the camps are positioned on the vertices of a convex polygon with Nvertices: P1, P2, …, PN (the vertices are enumerated around the polygon in counter-clockwise order.) In order to achieve absolute safety providing electricity to the camps, besides an electric supplying system, the host organization set up a path from a reserved electricity generator (which is placed in one of the camps) to every camp once, and the path's total length is minimum.
Problem
Given the coordinates of the polygons' vertices (the camps' positions), determine the length of the electric path corresponding to the host organization's arrangement.
Input
The first line contains the integer N (1 ≤ N ≤ 200). The i'th line of the next N lines contains two real numbers xi, yi, separated by a space, with no more than 3 digits after the decimal points, are vertex Pi's coordinates on the plane (with i = 1, 2, …, N). The length of the path connecting two vertex (xi, yi) and (xj, yj) is computed with the formula: sqrt((xi − xj)2 + (yi − yj)2).
Output
The only line should contain real number L (written in real number format, with 3 digits after the decimal point), which is the total length of the electric path.
Sample
input | output |
---|---|
4 50.0 1.0 5.0 1.0 0.0 0.0 45.0 0.0 |
50.211 |
Problem Source: The competition for selecting the Vietnam IOI team
Tags: none
Difficulty: 532
题意:顺序给出平面上凸多边形上n个点,问用一条线连接它们的最短长度。
分析:首先,可以感觉出线是不会交叉的。
然后我们证明一下:
先考虑四个点的情况。
取交叉的四个点。如果交叉,那么这四个点组成的四边形,肯定两条对角线都会被选择,然后再加上某一条边。
那么,显然,可以将一条对角边改为一条相邻的边(连接相邻的点)。这样显然更短。
考虑更多点的情况。
都可以选择两条相交的线的两个端点,共四个点。
然后将其他点抽象成边,由于是凸多边形,同样的性质必定满足。
故可以抽象为四个点的情况。
然后有这个性质就可以做了。
从两边开始dp,dp[i][j][0..1]表示从第i个到第j个,从左边还是右边开始连线。
转移显然了,只有两种。
1 /** 2 Create By yzx - stupidboy 3 */ 4 #include <cstdio> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cmath> 8 #include <deque> 9 #include <vector> 10 #include <queue> 11 #include <iostream> 12 #include <algorithm> 13 #include <map> 14 #include <set> 15 #include <ctime> 16 #include <iomanip> 17 using namespace std; 18 typedef long long LL; 19 typedef double DB; 20 #define MIT (2147483647) 21 #define INF (1000000001) 22 #define MLL (1000000000000000001LL) 23 #define sz(x) ((int) (x).size()) 24 #define clr(x, y) memset(x, y, sizeof(x)) 25 #define puf push_front 26 #define pub push_back 27 #define pof pop_front 28 #define pob pop_back 29 #define ft first 30 #define sd second 31 #define mk make_pair 32 33 inline int Getint() 34 { 35 int Ret = 0; 36 char Ch = ' '; 37 bool Flag = 0; 38 while(!(Ch >= '0' && Ch <= '9')) 39 { 40 if(Ch == '-') Flag ^= 1; 41 Ch = getchar(); 42 } 43 while(Ch >= '0' && Ch <= '9') 44 { 45 Ret = Ret * 10 + Ch - '0'; 46 Ch = getchar(); 47 } 48 return Flag ? -Ret : Ret; 49 } 50 51 const int N = 410; 52 struct Point 53 { 54 DB x, y; 55 56 inline void Read() 57 { 58 scanf("%lf%lf", &x, &y); 59 } 60 } arr[N]; 61 int n; 62 DB dp[N][N][2]; 63 bool visit[N][N][2]; 64 65 inline void Input() 66 { 67 scanf("%d", &n); 68 for(int i = 1; i <= n; i++) arr[i].Read(); 69 } 70 71 inline DB Sqr(DB x) 72 { 73 return x * x; 74 } 75 76 inline DB Dist(const Point &A, const Point &B) 77 { 78 return sqrt(Sqr(A.x - B.x) + Sqr(A.y - B.y)); 79 } 80 81 inline DB Work(int left, int right, bool type) 82 { 83 if(left >= right) return 0; 84 if(visit[left][right][type]) 85 return dp[left][right][type]; 86 visit[left][right][type] = 1; 87 DB ret = 1.0 * INF, cnt; 88 if(type == 0) 89 { 90 cnt = Dist(arr[left], arr[left + 1]); 91 cnt += Work(left + 1, right, 0); 92 ret = min(ret, cnt); 93 94 cnt = Dist(arr[left], arr[right]); 95 cnt += Work(left + 1, right, 1); 96 ret = min(ret, cnt); 97 } 98 else 99 { 100 cnt = Dist(arr[right], arr[right - 1]); 101 cnt += Work(left, right - 1, 1); 102 ret = min(ret, cnt); 103 104 cnt = Dist(arr[right], arr[left]); 105 cnt += Work(left, right - 1, 0); 106 ret = min(ret, cnt); 107 } 108 109 return dp[left][right][type] = ret; 110 } 111 112 inline void Solve() 113 { 114 for(int i = n + 1; i <= 2 * n; i++) 115 arr[i] = arr[i - n]; 116 117 DB ans = 1.0 * INF, cnt; 118 for(int i = 1; i <= n; i++) 119 { 120 cnt = Work(i, i + n - 1, 0); 121 ans = min(ans, cnt); 122 cnt = Work(i, i + n - 1, 1); 123 ans = min(ans, cnt); 124 } 125 126 printf("%.3lf\n", ans); 127 } 128 129 int main() 130 { 131 freopen("a.in", "r", stdin); 132 Input(); 133 Solve(); 134 return 0; 135 }