• uvalive 3890 Most Distant Point from the Sea


    题意:求一个凸多边形中一点到边的最大距离。

    思路:转换成在多边形内部,到每边距离为d的直线所围成的内多边形是否存在。也就是,二分距离+半平面交。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<iostream>
      6 #include<memory.h>
      7 #include<cstdlib>
      8 #include<vector>
      9 #define clc(a,b) memset(a,b,sizeof(a))
     10 #define LL long long int
     11 #define up(i,x,y) for(i=x;i<=y;i++)
     12 #define w(a) while(a)
     13 const double inf=0x3f3f3f3f;
     14 const int N = 4010;
     15 const double eps = 5*1e-13;
     16 const double PI = acos(-1.0);
     17 using namespace std;
     18 
     19 struct Point
     20 {
     21     double x, y;
     22     Point(double x=0, double y=0):x(x),y(y) { }
     23 };
     24 
     25 typedef Point Vector;
     26 
     27 Vector operator + (const Vector& A, const Vector& B)
     28 {
     29     return Vector(A.x+B.x, A.y+B.y);
     30 }
     31 Vector operator - (const Point& A, const Point& B)
     32 {
     33     return Vector(A.x-B.x, A.y-B.y);
     34 }
     35 Vector operator * (const Vector& A, double p)
     36 {
     37     return Vector(A.x*p, A.y*p);
     38 }
     39 double Dot(const Vector& A, const Vector& B)
     40 {
     41     return A.x*B.x + A.y*B.y;
     42 }
     43 double Cross(const Vector& A, const Vector& B)
     44 {
     45     return A.x*B.y - A.y*B.x;
     46 }
     47 double Length(const Vector& A)
     48 {
     49     return sqrt(Dot(A, A));
     50 }
     51 Vector Normal(const Vector& A)
     52 {
     53     double L = Length(A);
     54     return Vector(-A.y/L, A.x/L);
     55 }
     56 
     57 double PolygonArea(vector<Point> p)
     58 {
     59     int n = p.size();
     60     double area = 0;
     61     for(int i = 1; i < n-1; i++)
     62         area += Cross(p[i]-p[0], p[i+1]-p[0]);
     63     return area/2;
     64 }
     65 
     66 // 有向直线。它的左边就是对应的半平面
     67 struct Line
     68 {
     69     Point P;    // 直线上任意一点
     70     Vector v;   // 方向向量
     71     double ang; // 极角,即从x正半轴旋转到向量v所需要的角(弧度)
     72     Line() {}
     73     Line(Point P, Vector v):P(P),v(v)
     74     {
     75         ang = atan2(v.y, v.x);
     76     }
     77     bool operator < (const Line& L) const
     78     {
     79         return ang < L.ang;
     80     }
     81 };
     82 
     83 // 点p在有向直线L的左边(线上不算)
     84 bool OnLeft(const Line& L, const Point& p)
     85 {
     86     return Cross(L.v, p-L.P) > 0;
     87 }
     88 
     89 // 二直线交点,假定交点惟一存在
     90 Point GetLineIntersection(const Line& a, const Line& b)
     91 {
     92     Vector u = a.P-b.P;
     93     double t = Cross(b.v, u) / Cross(a.v, b.v);
     94     return a.P+a.v*t;
     95 }
     96 
     97 const double INF = 1e8;
     98 
     99 // 半平面交主过程
    100 vector<Point> HalfplaneIntersection(vector<Line> L)
    101 {
    102     int n = L.size();
    103     sort(L.begin(), L.end()); // 按极角排序
    104 
    105     int first, last;         // 双端队列的第一个元素和最后一个元素的下标
    106     vector<Point> p(n);      // p[i]为q[i]和q[i+1]的交点
    107     vector<Line> q(n);       // 双端队列
    108     vector<Point> ans;       // 结果
    109 
    110     q[first=last=0] = L[0];  // 双端队列初始化为只有一个半平面L[0]
    111     for(int i = 1; i < n; i++)
    112     {
    113         while(first < last && !OnLeft(L[i], p[last-1])) last--;
    114         while(first < last && !OnLeft(L[i], p[first])) first++;
    115         q[++last] = L[i];
    116         if(fabs(Cross(q[last].v, q[last-1].v)) < eps)   // 两向量平行且同向,取内侧的一个
    117         {
    118             last--;
    119             if(OnLeft(q[last], L[i].P)) q[last] = L[i];
    120         }
    121         if(first < last) p[last-1] = GetLineIntersection(q[last-1], q[last]);
    122     }
    123     while(first < last && !OnLeft(q[first], p[last-1])) last--; // 删除无用平面
    124     if(last - first <= 1) return ans; // 空集
    125     p[last] = GetLineIntersection(q[last], q[first]); // 计算首尾两个半平面的交点
    126 
    127     // 从deque复制到输出中
    128     for(int i = first; i <= last; i++) ans.push_back(p[i]);
    129     return ans;
    130 }
    131 
    132 int main()
    133 {
    134     int n;
    135     while(scanf("%d", &n) == 1 && n)
    136     {
    137         vector<Vector> p, v, normal;
    138         int m, x, y;
    139         for(int i = 0; i < n; i++)
    140         {
    141             scanf("%d%d", &x, &y);
    142             p.push_back(Point(x,y));
    143         }
    144         if(PolygonArea(p) < 0) reverse(p.begin(), p.end());
    145 
    146         for(int i = 0; i < n; i++)
    147         {
    148             v.push_back(p[(i+1)%n]-p[i]);
    149             normal.push_back(Normal(v[i]));
    150         }
    151 
    152         double left = 0, right = 20000;
    153         while(right-left > 1e-6)
    154         {
    155             vector<Line> L;
    156             double mid = left+(right-left)/2;
    157             for(int i = 0; i < n; i++) L.push_back(Line(p[i]+normal[i]*mid, v[i]));//平移直线
    158             vector<Point> poly = HalfplaneIntersection(L);
    159             if(poly.empty()) right = mid;
    160             else left = mid;
    161         }
    162         printf("%.6lf
    ", left);
    163     }
    164     return 0;
    165 }
    View Code
  • 相关阅读:
    [hdu 2089] 不要62 数位dp|dfs 入门
    [poj 2456] Aggressive cows 二分
    NOIP 2016 DAY 1 爆炸记
    【模板】kmp
    【模板】LCA
    NOIP 之前的吐槽
    【模板】树状数组
    【模板】线段树
    【模板】高精度
    2016/11/15
  • 原文地址:https://www.cnblogs.com/ITUPC/p/4887675.html
Copyright © 2020-2023  润新知