LA 3890 (半平面交) Most Distant Point from the Sea
生活随笔
收集整理的這篇文章主要介紹了
LA 3890 (半平面交) Most Distant Point from the Sea
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題意:
給出一個凸n邊形,求多邊形內部一點使得該點到邊的最小距離最大。
分析:
最小值最大可以用二分。
多邊形每條邊的左邊是一個半平面,將這n個半平面向左移動距離x,則將這個凸多邊形縮小了。如果這n個半平面交非空,則存在這樣距離為x的點,反之則不存在。
?
半平面交的代碼還沒有完全理解。
和凸包類似,先對這些半平面進行極角排序。每次新加入的平面可能讓隊尾的平面變得“無用”,從而需要刪除。由于極角序是環形的,所以也可能讓隊首元素變得“無用”。所以用雙端隊列來維護。
?
1 //#define LOCAL 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 using namespace std; 8 9 const double eps = 1e-6; 10 11 struct Point 12 { 13 double x, y; 14 Point(double x=0, double y=0):x(x), y(y){} 15 }; 16 typedef Point Vector; 17 Point operator + (Point A, Point B) { return Point(A.x+B.x, A.y+B.y); } 18 Point operator - (Point A, Point B) { return Point(A.x-B.x, A.y-B.y); } 19 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); } 20 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); } 21 double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; } 22 double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; } 23 double Length(Vector A) { return sqrt(Dot(A, A)); } 24 Vector Normal(Vector A) { double l = Length(A); return Vector(-A.y/l, A.x/l); } 25 26 double PolygonArea(const vector<Point>& p) 27 { 28 double ans = 0.0; 29 int n = p.size(); 30 for(int i = 1; i < n-1; ++i) 31 ans += Cross(p[i]-p[0], p[i+1]-p[0]); 32 return ans/2; 33 } 34 35 struct Line 36 { 37 Point p; 38 Vector v; 39 double ang; 40 Line() {} 41 Line(Point p, Vector v):p(p), v(v) { ang = atan2(v.y, v.x); } 42 bool operator < (const Line& L) const 43 { 44 return ang < L.ang; 45 } 46 }; 47 48 bool OnLeft(const Line& L, const Point& p) 49 { return Cross(L.v, p-L.p) > 0; } 50 51 Point GetLineIntersection(const Line& a, const Line& b) 52 { 53 Vector u = a.p-b.p; 54 double t = Cross(b.v, u) / Cross(a.v, b.v); 55 return a.p + a.v*t; 56 } 57 58 vector<Point> HalfplaneIntersection(vector<Line> L) 59 { 60 int n = L.size(); 61 sort(L.begin(), L.end()); 62 63 int first, last; 64 vector<Point> p(n); 65 vector<Line> q(n); 66 vector<Point> ans; 67 68 q[first=last=0] = L[0]; 69 for(int i = 1; i < n; ++i) 70 { 71 while(first < last && !OnLeft(L[i], p[last-1])) last--; 72 while(first < last && !OnLeft(L[i], p[first])) first++; 73 q[++last] = L[i]; 74 if(fabs(Cross(q[last].v, q[last-1].v)) < eps) //è?1?á??±????DD£?è??ú2àμ????? 75 { 76 last--; 77 if(OnLeft(q[last], L[i].p)) q[last] = L[i]; 78 } 79 if(first < last) p[last-1] = GetLineIntersection(q[last-1], q[last]); 80 } 81 while(first < last && !OnLeft(q[first], p[last-1])) last--; 82 if(last - first <= 1) return ans; 83 p[last] = GetLineIntersection(q[last], q[first]); 84 85 for(int i = first; i <= last; ++i) ans.push_back(p[i]); 86 return ans; 87 } 88 89 int main(void) 90 { 91 #ifdef LOCAL 92 freopen("3890in.txt", "r", stdin); 93 #endif 94 95 int n; 96 while(scanf("%d", &n) == 1 && n) 97 { 98 vector<Point> p, v, normal; 99 int m, x, y; 100 for(int i = 0; i < n; ++i) { scanf("%d%d", &x, &y); p.push_back(Point(x, y)); } 101 if(PolygonArea(p) < 0) reverse(p.begin(), p.end()); 102 103 for(int i = 0; i < n; ++i) 104 { 105 v.push_back(p[(i+1)%n] - p[i]); 106 normal.push_back(Normal(v[i])); 107 } 108 109 double left = 0, right = 20000; 110 while(right - left > 5e-7) 111 { 112 vector<Line> L; 113 double mid = (right + left) / 2; 114 for(int i = 0; i < n; ++i) L.push_back(Line(p[i] + normal[i]*mid, v[i])); 115 vector<Point> Poly = HalfplaneIntersection(L); 116 if(Poly.empty()) right = mid; 117 else left = mid; 118 } 119 printf("%.6lf\n", left); 120 } 121 122 return 0; 123 } 代碼君?
轉載于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4039878.html
總結
以上是生活随笔為你收集整理的LA 3890 (半平面交) Most Distant Point from the Sea的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ZOJ 3829 Known Notat
- 下一篇: Oracle函数的定义