UVALive 4992 Jungle Outpost(半平面交判存)

Jungle Outpost

Time limit: 15.000 seconds

Description

There is a military base lost deep in the jungle. It is surrounded by n watchtowers with ultrasonic generators. In this problem watchtowers are represented by points on a plane.

Watchtowers generate ultrasonic field and protect all objects that are strictly inside the towers' convex hull. There is no tower strictly inside the convex hull and no three towers are on a straight line.

The enemy can blow up some towers. If this happens, the protected area is reduced to a convex hull of the remaining towers.

epsfbox{p4992.eps}

The base commander wants to build headquarters inside the protected area. In order to increase its security, he wants to maximize the number of towers that the enemy needs to blow up to make the headquarters unprotected.

Input

The input file contains several test cases, each of them as described below.

The first line of each one of the cases contains a single integer n(3$ le$n$ le$50000) -- the number of watchtowers. The next n lines of the input file contain the Cartesian coordinates of watchtowers, one pair of coordinates per line. Coordinates are integer and do not exceed106 by absolute value. Towers are listed in the order of traversal of their convex hull in clockwise direction.

Output

For each test case, write to the output file the number of watchtowers the enemy has to blow up to compromise headquarters protection if the headquarters are placed optimally.

Sample Input

3 
0 0 
50 50 
60 10 
5 
0 0 
0 10 
10 20 
20 10 
25 0

Sample Output

1
2

二分答案,判半平面交是否存在。注意:连续销毁几个点比分开销毁的做法更优。

建立半平面是用直线表示的 。然后直线的左边是代表有面积的,所以要注意下直线的向量方向。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <algorithm>

using namespace std;

#define X first
#define Y second
#define root 1,n,1
#define lr rt<<1
#define rr rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1

typedef long long LL;
typedef pair<int,int> pii;
const int N = 50050 ;
const int inf = 1e9+7;
const double eps = 1e-8;
int n ;

inline int dcmp(double x){
    if( fabs(x)<eps ) return 0;
    return x<0?-1:1;
}
struct Point {
    double x , y ;
    Point(){};
    Point(double x,double y):x(x),y(y){};
    bool operator < ( const Point &a ) const {
        return dcmp(x-a.x) < 0 || ( dcmp(x-a.x)==0 && dcmp(y-a.y) < 0 );
    }
}e[N];
typedef Point Vector;
struct Line {
    Point p;
    Vector v ;          // directional vector
    double ang ;
    Line(){};
    Line( Point p , Vector v ):p(p),v(v){ ang = atan2(v.y,v.x); }
    bool operator < ( const Line &L ) const {
        return ang < L.ang;
    }
};

Point operator - ( Point a , Point b ){ return Point(a.x-b.x,a.y-b.y); }
Point operator + ( Point a , Point b ){ return Point(a.x+b.x,a.y+b.y); }
Point operator * ( Point a , double p ){ return Point(a.x*p,a.y*p); }

inline double Cross(Point a , Point b ) { return a.x*b.y-a.y*b.x;}
bool OnLeft( Line L , Point p ) {
    return Cross( L.v , p-L.p ) > 0 ;
}

Point GetIntersection( Line a , Line b ){
    Vector u = a.p - b.p ;
    double t = Cross(b.v,u) / Cross(a.v,b.v);
    return a.p + a.v*t;
}

bool HPI( Line* L , int n  ) {
    sort( L , L + n );
    int first , last ;          //deque ,
    Point *p = new Point[n];    //p[i] is q[i] and q[i+1] 's intersection point
    Line *q = new Line[n];
    q[first=last=0] = L[0];
    for( int i = 1 ; i < n ; ++i ) {
        while( first < last && !OnLeft( L[i], p[last-1] )) last--;
        while( first < last && !OnLeft( L[i], p[first] )) first++;
        q[++last] = L[i];
        if( fabs(Cross(q[last].v,q[last-1].v)) < eps ) {
            last--;
            if( OnLeft( q[last] , L[i].p) ) q[last] = L[i];
        }
        if( first < last ) p[last-1] = GetIntersection(q[last-1],q[last]);
    }
    while( first < last && !OnLeft( q[first],p[last-1])) last--;
    // delete useless plane
    if( last - first <= 1 ) return false ;
    return true ;
}

Line L[N];

bool ok( int num ) {
    int tot = 0 ;
    for( int i = 0 ; i < n ; ++i ) {
        L[tot++] = Line( e[(i+num+1)%n],e[i]-e[(i+num+1)%n] );   // convex in clockwise direction
    }
    if( !HPI(L,tot) ) return true ;
    return false ;
}

void Run() {

    for( int i = 0 ; i < n ; ++i ) {
        scanf("%lf%lf",&e[i].x,&e[i].y);
    }
    if( n == 3 ) { puts("1"); return ; }
    int ans = 0 , l = 0 , r = n - 3 ;
    while( l <= r ) {
        int mid = (l+r)>>1;
        if( ok(mid) )
            ans = mid , r = mid - 1 ;
        else
            l = mid + 1 ;
    }
    printf("%d
",ans);
}

int main(){
    #ifdef LOCAL
        freopen("in.txt","r",stdin);
    #endif // LOCAL
    while( scanf("%d",&n)!=EOF ) Run();
}
View Code
only strive for your goal , can you make your dream come true ?
原文地址:https://www.cnblogs.com/hlmark/p/4151856.html