bzoj 1020[SHOI2008]安全的航线flight - 迭代+二分
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
1 2
-9 -6
5 1
3
0 16
-16 -12
17 -6
-9 -6
5 1
3
0 16
-16 -12
17 -6
Sample Output
0.00
是一道迭代思想的应用 详情—— 莫涛《迭代思想的应用》
具体的思路就是我们先将初始的所有飞行线路的线段都放入一个队列中
然后先求出线段两端点到大陆的最近点,然后二分找到线段上到两点距离相同的点, 记为d
如果d < ans, 我们就没有必要再考虑这条线段。
因为一个线段上的点到大陆的最短距离必然 <d
可以想象距离为d的点向左右移动距离变小
之后我们将线段从中间分为两段放入队列
直到队列为空
代码恶心的要死
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 */