zoukankan      html  css  js  c++  java
  • uvalive 4992 Jungle Outpost

    题意:一个凸边型,目标在凸边型内且最优。问最多删除几个点使目标暴露在新凸边型外面。

    思路:二分+半平面相交。

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<vector>
      4 #include<algorithm>
      5 using namespace std;
      6 
      7 struct Point
      8 {
      9     double x, y;
     10     Point(double x=0, double y=0):x(x),y(y) { }
     11 };
     12 
     13 typedef Point Vector;
     14 
     15 Vector operator + (const Vector& A, const Vector& B)
     16 {
     17     return Vector(A.x+B.x, A.y+B.y);
     18 }
     19 Vector operator - (const Point& A, const Point& B)
     20 {
     21     return Vector(A.x-B.x, A.y-B.y);
     22 }
     23 Vector operator * (const Vector& A, double p)
     24 {
     25     return Vector(A.x*p, A.y*p);
     26 }
     27 double Dot(const Vector& A, const Vector& B)
     28 {
     29     return A.x*B.x + A.y*B.y;
     30 }
     31 double Cross(const Vector& A, const Vector& B)
     32 {
     33     return A.x*B.y - A.y*B.x;
     34 }
     35 double Length(const Vector& A)
     36 {
     37     return sqrt(Dot(A, A));
     38 }
     39 Vector Normal(const Vector& A)
     40 {
     41     double L = Length(A);
     42     return Vector(-A.y/L, A.x/L);
     43 }
     44 
     45 double PolygonArea(vector<Point> p)
     46 {
     47     int n = p.size();
     48     double area = 0;
     49     for(int i = 1; i < n-1; i++)
     50         area += Cross(p[i]-p[0], p[i+1]-p[0]);
     51     return area/2;
     52 }
     53 
     54 // 有向直线。它的左边就是对应的半平面
     55 struct Line
     56 {
     57     Point P;    // 直线上任意一点
     58     Vector v;   // 方向向量
     59     double ang; // 极角,即从x正半轴旋转到向量v所需要的角(弧度)
     60     Line() {}
     61     Line(Point P, Vector v):P(P),v(v)
     62     {
     63         ang = atan2(v.y, v.x);
     64     }
     65     bool operator < (const Line& L) const
     66     {
     67         return ang < L.ang;
     68     }
     69 };
     70 
     71 // 点p在有向直线L的左边(线上不算)
     72 bool OnLeft(const Line& L, const Point& p)
     73 {
     74     return Cross(L.v, p-L.P) > 0;
     75 }
     76 
     77 // 二直线交点,假定交点惟一存在
     78 Point GetLineIntersection(const Line& a, const Line& b)
     79 {
     80     Vector u = a.P-b.P;
     81     double t = Cross(b.v, u) / Cross(a.v, b.v);
     82     return a.P+a.v*t;
     83 }
     84 
     85 const double eps = 1e-6;
     86 
     87 // 半平面交主过程
     88 vector<Point> HalfplaneIntersection(vector<Line>& L)
     89 {
     90     int n = L.size();
     91     sort(L.begin(), L.end()); // 按极角排序
     92 
     93     int first, last;         // 双端队列的第一个元素和最后一个元素的下标
     94     vector<Point> p(n);      // p[i]为q[i]和q[i+1]的交点
     95     vector<Line> q(n);       // 双端队列
     96     vector<Point> ans;       // 结果
     97 
     98     q[first=last=0] = L[0];  // 双端队列初始化为只有一个半平面L[0]
     99     for(int i = 1; i < n; i++)
    100     {
    101         while(first < last && !OnLeft(L[i], p[last-1])) last--;
    102         while(first < last && !OnLeft(L[i], p[first])) first++;
    103         q[++last] = L[i];
    104         if(fabs(Cross(q[last].v, q[last-1].v)) < eps)   // 两向量平行且同向,取内侧的一个
    105         {
    106             last--;
    107             if(OnLeft(q[last], L[i].P)) q[last] = L[i];
    108         }
    109         if(first < last) p[last-1] = GetLineIntersection(q[last-1], q[last]);
    110     }
    111     while(first < last && !OnLeft(q[first], p[last-1])) last--; // 删除无用平面
    112     if(last - first <= 1) return ans; // 空集
    113     p[last] = GetLineIntersection(q[last], q[first]); // 计算首尾两个半平面的交点
    114 
    115     // 从deque复制到输出中
    116     for(int i = first; i <= last; i++) ans.push_back(p[i]);
    117     return ans;
    118 }
    119 
    120 const int maxn = 50000 + 10;
    121 int n;
    122 Point P[maxn];
    123 
    124 // 连续m个点是否可以保证炸到总部
    125 bool check(int m)
    126 {
    127     vector<Line> lines;
    128     for(int i = 0; i < n; i++)
    129         lines.push_back(Line(P[(i+m+1)%n], P[i]-P[(i+m+1)%n]));//相当于从起点0到((i+m+1)%n)这两点延顺时针方向之间的点被删除。应为向量指向起点0,只有向量左边的点符合要求,右边自然被排除。
    130     return HalfplaneIntersection(lines).empty();
    131 }
    132 
    133 int solve()
    134 {
    135     if(n == 3) return 1;
    136     int L = 1, R = n-3, M; // 炸n-3个点一定可以摧毁
    137     while(L < R)
    138     {
    139         M = L + (R-L)/2;
    140         if(check(M)) R = M;
    141         else L = M+1;
    142     }
    143     return L;
    144 }
    145 
    146 int main()
    147 {
    148     while(scanf("%d", &n) == 1 && n)
    149     {
    150         for(int i = 0; i < n; i++)
    151         {
    152             int x, y;
    153             scanf("%d%d", &x, &y);
    154             P[i] = Point(x, y);
    155         }
    156         printf("%d
    ", solve());
    157     }
    158     return 0;
    159 }
    View Code
  • 相关阅读:
    mac xcode 编辑 plist 文件 value列展示不全
    React Native 打包异常:Connect to maven.google.com failed: connect timed out(原创)
    React Native 打包异常:Android resource linking failed(原创)
    面向交易的日内高频量化交易平台笔记
    wpf 样式继承
    wpf staticresource 是不允许向前引用(forward reference)的
    C# 32位程序访问64位注册表
    wpf 可视化树的注意点
    关于64位操作系统使用C#访问注册表失败的问题
    关于 vs 2012 键盘无法输入的问题
  • 原文地址:https://www.cnblogs.com/ITUPC/p/4890474.html
Copyright © 2011-2022 走看看