zoukankan      html  css  js  c++  java
  • 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)    //Èç¹ûÁ½Ö±ÏßƽÐУ¬È¡ÄÚ²àµÄÄǸö 
     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
    ", left);
    120     }
    121     
    122     return 0;
    123 }
    代码君
  • 相关阅读:
    期末考试结束啦!!!
    【sdut2878】Circle
    【HDU4035】Maze
    【ZOJ3329】One Person Game
    【POJ2151】Check the difficulty of problems
    【CodeForces148D】Bag of mice
    【POJ2096】Collecting Bugs
    【HDU3853】LOOPS
    【HDU4405】Aeroplane_chess
    「Luogu P5826 【模板】子序列自动机」
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4039878.html
Copyright © 2011-2022 走看看