UVa 1475 (二分+半平面交) Jungle Outpost

题意:

有n个瞭望塔构成一个凸n边形,敌人会炸毁一些瞭望台,剩下的瞭望台构成新的凸包。在凸多边形内部选择一个点作为总部,使得敌人需要炸毁的瞭望塔最多才能使总部暴露出来。输出敌人需要炸毁的数目。

分析:

在炸毁同样数量的瞭望塔时,如何爆破才能使暴露出的面积最大。那就是集中火力炸掉连续的几个瞭望塔。直觉上是这样的,我不会证明这个结论。因为是连续爆破,所以k次爆破后还保留的部分就是一个半平面,枚举这k个爆破点,如果这些半平面交非空则总部可以设在这里。

k值是通过二分来确定的,下界是1,上界是n-3(这个需要好好想一下,想不清楚的话即使写n应该也可以)。

 

  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 int maxn = 50000 + 10;

 10 const double eps = 1e-6;

 11 typedef long long LL;

 12 

 13 void scan( int &x )

 14 {

 15     char c;

 16     while( c = getchar(), c < '0' || c > '9' );

 17     x = c - '0';

 18     while( c = getchar(), c >= '0' && c <= '9' ) x = x*10 - c + '0';

 19 }

 20 

 21 struct Point

 22 {

 23     double x, y;

 24     Point(double x=0, double y=0):x(x), y(y) {}

 25 };

 26 typedef Point Vector;

 27 Point operator + (const Point& a, const Point& b) { return Point(a.x+b.x, a.y+b.y); }

 28 Point operator - (const Point& a, const Point& b) { return Point(a.x-b.x, a.y-b.y); }

 29 Vector operator * (const Vector& a, double p) { return Vector(a.x*p, a.y*p); }

 30 double Dot(const Vector& a, const Vector& b) { return a.x*b.x + a.y*b.y; }

 31 double Cross(const Vector& a, const Vector& b) { return a.x*b.y - a.y*b.x; }

 32 double Length(const Vector& a) { return sqrt(Dot(a, a)); }

 33 Vector Normal(const Vector& a)

 34 {

 35     double l = Length(a);

 36     return Vector(-a.y/l, a.x/l);

 37 }

 38 

 39 double PolygonArea(const vector<Point>& p)

 40 {

 41     int n = p.size();

 42     double ans = 0.0;

 43     for(int i = 1; i < n-1; ++i)

 44         ans += Cross(p[i]-p[0], p[i+1]-p[0]);

 45     return ans/2;

 46 }

 47 

 48 struct Line

 49 {

 50     Point P;

 51     Vector v;

 52     double ang;

 53     Line() {}

 54     Line(Point p, Vector v):P(p), v(v) { ang = atan2(v.y, v.x); }

 55     bool operator < (const Line& L) const

 56     {

 57         return ang < L.ang;

 58     }

 59 };

 60 

 61 bool OnLeft(const Line& L, Point p)

 62 {

 63     return Cross(L.v, p-L.P) > 0;

 64 }

 65 

 66 Point GetLineIntersection(const Line& a, const Line& b)

 67 {

 68     Vector u = a.P - b.P;

 69     double t = Cross(b.v, u) / Cross(a.v, b.v);

 70     return a.P + a.v*t;

 71 }

 72 

 73 vector<Point> HalfplaneIntersection(vector<Line>& L)

 74 {

 75     int n = L.size();

 76     //sort(L.begin(), L.end());

 77     

 78     vector<Point> p(n);

 79     vector<Line> q(n);

 80     vector<Point> ans;

 81     int first, last;

 82     

 83     q[first=last=0] = L[0];

 84     for(int i = 1; i < n; ++i)

 85     {

 86         while(first < last && !OnLeft(L[i], p[last-1])) last--;

 87         while(first < last && !OnLeft(L[i], p[first])) first++;

 88         q[++last] = L[i];

 89         if(fabs(Cross(q[last].v, q[last-1].v)) < eps)

 90         {

 91             last--;

 92             if(OnLeft(q[last], L[i].P)) q[last] = L[i];

 93         }

 94         if(first < last) p[last-1] = GetLineIntersection(q[last], q[last-1]);

 95     }

 96     while(first < last && !OnLeft(q[first], p[last-1])) last--;

 97     if(last-first <= 1) return ans;

 98     p[last] = GetLineIntersection(q[first], q[last]);

 99     

100     for(int i = first; i <= last; ++i) ans.push_back(p[i]);

101     return ans;

102 }

103 

104 Point p[maxn];

105 int n;

106 

107 bool check(int m)

108 {

109     vector<Line> lines;

110     for(int i = 0; i < n; ++i)

111         lines.push_back(Line(p[(i+m+1)%n], p[i]-p[(i+m+1)%n]));

112     return HalfplaneIntersection(lines).empty();

113 }

114 

115 int solve()

116 {

117     if(n==3) return 1;

118     int L = 1, R = n-3, M;

119     while(L < R)

120     {

121         M = L + (R-L)/2;

122         if(check(M)) R = M;

123         else L = M+1;

124     }

125     return L;

126 }

127 

128 int main(void)

129 {

130     #ifdef LOCAL

131         freopen("4992in.txt", "r", stdin);

132     #endif

133     

134     int x, y;

135     while(scanf("%d", &n) == 1 && n)

136     {

137         for(int i = 0; i < n; ++i)

138         {

139             scanf("%d%d", &x, &y);

140             p[i] = Point(x, y);

141         }

142         printf("%d\n", solve());

143     }

144     

145     return 0;

146 }
代码君

 

你可能感兴趣的:(post)