1020: [SHOI2008]安全的航线flight
Time Limit: 5 Sec Memory Limit: 162 MBDescription
在设计航线的时候,安全是一个很重要的问题。首先,最重要的是应采取一切措施确保飞行不会发生任何事故
,但同时也需要做好最坏的打算,一旦事故发生,就要确保乘客有尽量高的生还几率。当飞机迫降到海上的时候,
最近的陆地就是一个关键的因素。航线中最危险的地方就是距离最近的陆地最远的地方,我们称这种点为这条航线
“孤地点”。孤地点到最近陆地的距离被称为“孤地距离”。作为航空公司的高级顾问,你接受的第一个任务就是
尽量找出一条航线的孤地点,并计算这条航线的孤地距离。为了简化问题,我们认为地图是一个二维平面,陆地可
以用多边形近似,飞行线路为一条折线。航线的起点和终点都在陆地上,但中间的转折点是可能在海上(如下图所
示,方格标示出了孤地点)。
Input
输入的第一行包括两个整数C和N(1≤C≤20,2≤N≤20),分别代表陆地的数目的航线的转折点的数目。接下
来有N行,每行有两个整数x,y。(x,y)表示一个航线转折点的坐标,第一个转折点为航线的起点,最后一个转折点
为航线的终点。接下来的输入将用来描述C块大陆。每块输入由一个正整数M开始(M≤30),M表示多边形的顶点个
数,接下来的M行,每行会包含两个整数x,y,(x,y)表示多边形的一个顶点坐标,我们保证这些顶点以顺时针或逆
时针给出了该多边形的闭包,不会出现某些边相交的情况。此外我们也保证输入数据中任何两块大陆不会相交。输
入的所有坐标将保证在-10000到10000的范围之间。
Output
输出一个浮点数,表示航线的孤地距离,数据保留2位小数。
Sample Input
-9 -6
5 1
3
0 16
-16 -12
17 -6
Sample Output
1 #include <iostream> 2 #include <queue> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <cstdio> 7 #define LL long long 8 9 using namespace std; 10 11 int C, N; 12 double ans = 0; 13 14 double eps = 1e-14; 15 inline LL read() 16 { 17 LL x = 0, w = 1; char ch = 0; 18 while(ch < ‘0‘ || ch > ‘9‘) { 19 if(ch == ‘-‘) { 20 w = -1; 21 } 22 ch = getchar(); 23 } 24 while(ch >= ‘0‘ && ch <= ‘9‘) { 25 x = x * 10 + ch - ‘0‘; 26 ch = getchar(); 27 } 28 return x * w; 29 } 30 31 struct vec { 32 double x, y; 33 }; 34 35 struct NODE { 36 double x, y; 37 } p1, p2, tt, mid, l, r, p; 38 39 struct node { 40 double x[30], y[30]; 41 int M; 42 } n, land[40]; 43 44 struct edge { 45 double x1, y1; 46 double x2, y2; 47 } la[100], fl[100], temp, t; 48 49 double disnode(NODE a, NODE b) 50 { 51 return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); 52 } 53 54 double dis(double x1, double y1, double x2, double y2) 55 { 56 return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); 57 } 58 59 NODE operator +(NODE a, NODE b) 60 { 61 NODE temp; 62 temp.x = a.x + b.x; 63 temp.y = a.y + b.y; 64 return temp; 65 } 66 67 NODE operator /(NODE a, double k) 68 { 69 NODE temp; 70 temp.x = a.x / k; 71 temp.y = a.y / k; 72 return temp; 73 } 74 bool in(double x, double y, int k) 75 { 76 int cnt = 0; 77 for(int i = 0; i < land[k].M; i++) { 78 double x1 = land[k].x[i], y1 = land[k].y[i]; 79 double x2 = land[k].x[(i + 1) % land[k].M], y2 = land[k].y[(i + 1) % land[k].M]; 80 if((x1 == x && y1 == y) || (x2 == x && y2 == y)) { 81 return true; 82 } 83 if((y1 < y && y2 >= y) || (y1 >= y && y2 < y)) { 84 double xx = x1 + (y - y1) * (x2 - x1) / (y2 - y1); 85 if(xx == x) { 86 return true; 87 } 88 if(xx > x) { 89 cnt++; 90 } 91 } 92 } 93 return cnt % 2; 94 } 95 96 97 NODE PointToSegDist(double x, double y, double x1, double y1, double x2, double y2) 98 { 99 double cross = (x2 - x1) * (x - x1) + (y2 - y1) * (y - y1); 100 if (cross <= 0) { 101 tt.x = x1, tt.y = y1; 102 return tt; 103 } 104 double d2 = (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); 105 if (cross >= d2) { 106 tt.x = x2, tt.y = y2; 107 return tt; 108 } 109 double r = cross / d2; 110 double px = x1 + (x2 - x1) * r; 111 double py = y1 + (y2 - y1) * r; 112 tt.x = px, tt.y = py; 113 return tt; 114 } 115 NODE cal(double x, double y) 116 { 117 double dmin = 1e9; 118 for(int i = 1; i <= C; i++) { 119 if(in(x, y, i)) { 120 tt.x = x, tt.y = y; 121 return tt; 122 } 123 } 124 for(int i = 1; i <= C; i++) { 125 for(int j = 0; j < land[i].M; j++) { 126 tt = PointToSegDist(x, y, land[i].x[j], land[i].y[j], land[i].x[(j + 1) % land[i].M], land[i].y[(j + 1) % land[i].M]); 127 if(dmin > dis(x, y, tt.x, tt.y)) { 128 dmin = dis(x, y, tt.x, tt.y); 129 p.x = tt.x, p.y = tt.y; 130 } 131 } 132 } 133 ans = max(ans, dis(x, y, p.x, p.y)); 134 135 return p; 136 } 137 138 queue<edge> q; 139 int sum = 0; 140 int main() 141 { 142 C = read(), N = read(); 143 for(int i = 0; i < N; i++) { 144 scanf("%lf%lf", &n.x[i], &n.y[i]); 145 } 146 for(int j = 0; j < N; j++) { 147 temp.x1 = n.x[j], temp.y1 = n.y[j]; 148 temp.x2 = n.x[(j + 1) % N], temp.y2 = n.y[(j + 1) % N]; 149 q.push(temp); 150 } 151 for(int i = 1; i <= C; i++) { 152 land[i].M = read(); 153 for(int j = 0; j < land[i].M; j++) { 154 scanf("%lf%lf", &land[i].x[j], &land[i].y[j]); 155 } 156 } 157 while(!q.empty()) { 158 temp = q.front(); 159 //cout<<temp.x1<<" "<<temp.y1<<" "<<temp.x2<<" "<<temp.y2<<endl; 160 q.pop(); 161 double x1 = temp.x1, x2 = temp.x2, y1 = temp.y1, y2 = temp.y2; 162 p1 = cal(x1, y1), p2 = cal(x2, y2); 163 l.x = x1, l.y = y1, r.x = x2, r.y = y2; 164 while(disnode(r, l) >= eps) { 165 // cout<<l.x<<" "<<l.y<<" "<<endl<<r.x<<" "<<r.y<<" "<<endl<<disnode(l, r)<<endl<<endl; 166 mid = (l + r) / 2; 167 if (disnode(mid, p1) < disnode(mid, p2)) { 168 l = mid; 169 } else { 170 r = mid; 171 } 172 } 173 cal(mid.x, mid.y); 174 if(min(disnode(l, p1), disnode(r, p2)) > ans + 0.005) { 175 t = temp; 176 t.x2 = mid.x, t.y2 = mid.y; 177 q.push(t); 178 t = temp; 179 t.x1 = mid.x, t.y1 = mid.y; 180 q.push(t); 181 } 182 } 183 printf("%.2lf", ans); 184 return 0; 185 } 186 187 188 /* 189 1 2 190 191 -9 -6 192 193 5 1 194 195 3 196 197 0 16 198 199 -16 -12 200 201 17 -6 202 203 */