hdu 3761 半平面交
转:http://blog.csdn.net/acm_cxlove/article/details/7854526
上图表示当只需要删除一个点时的状况,其中红色的区域建立了司令部,不论删除任何的一个点,都不可能找到司令部,因此最大的要删除的点大于1,所以通过二分需要删除的最大值即可。
1 /* 2 题意:给出n个点组成的多边形,内部会选择最安全的地方建一个司令部,求最多删除多少个点 3 时,司令部有可能暴露; 4 5 题解:半平面交 6 显然(=。=)删除连续的点会使得凸多边形的面积变最多,每次删除x个点,然后加上一条边(求半平 7 面交可行域所需的边),遍历n个点得出n条边,则这些直线所围成的就是可行域,求可行域面积为 8 0的时候的x最大值 9 */ 10 #include<iostream> 11 #include<cstdio> 12 #include<algorithm> 13 #include<cmath> 14 #define eps 1e-10 15 #define N 50005 16 #define zero(a) (fabs(a)<eps) 17 using namespace std; 18 struct Point { 19 double x,y; 20 Point(){} 21 Point(double tx,double ty){x=tx;y=ty;} 22 }p[N],q[N]; 23 int n,m; 24 struct Segment{ 25 Point s,e; 26 double angle; 27 void get_angle(){angle=atan2(e.y-s.y,e.x-s.x);} 28 }seg[N]; 29 30 Segment deq[N]; 31 double xmul(Point p0,Point p1,Point p2){ 32 return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); 33 } 34 double Get_Area(Point pt[],int n){ 35 double area=0; 36 for(int i=1;i<n-1;i++) 37 area+=xmul(pt[0],pt[i],pt[i+1]); 38 return fabs(area)/2; 39 } 40 Point Get_Intersect(Segment s1,Segment s2){ 41 double u=xmul(s1.s,s1.e,s2.s),v=xmul(s1.e,s1.s,s2.e); 42 Point t; 43 t.x=(s2.s.x*v+s2.e.x*u)/(u+v);t.y=(s2.s.y*v+s2.e.y*u)/(u+v); 44 return t; 45 } 46 void HalfPlaneIntersect(Segment seg[],int n){ 47 int idx; 48 for(int i=0;i<n;i++) 49 if(seg[i].angle+eps<seg[(i+1)%n].angle&&seg[i].angle+eps<seg[(i-1+n)%n].angle){ 50 idx=i; 51 break; 52 } 53 54 deq[0]=seg[idx];deq[1]=seg[(idx+1)%n]; 55 int head=0,tail=1; 56 idx=(idx+2)%n; 57 for(int i=2;i<n;i++,idx=(idx+1)%n){ 58 while(head<tail&&xmul(seg[idx].s,seg[idx].e,Get_Intersect(deq[tail],deq[tail-1]))<-eps) tail--; 59 while(head<tail&&xmul(seg[idx].s,seg[idx].e,Get_Intersect(deq[head],deq[head+1]))<-eps) head++; 60 deq[++tail]=seg[idx]; 61 } 62 while(head<tail&&xmul(deq[head].s,deq[head].e,Get_Intersect(deq[tail],deq[tail-1]))<-eps) tail--; 63 while(head<tail&&xmul(deq[tail].s,deq[tail].e,Get_Intersect(deq[head],deq[head+1]))<-eps) head++; 64 m=0; 65 if(tail==head) return; 66 for(int i=head;i<tail;i++){ 67 q[m++]=Get_Intersect(deq[i],deq[i+1]); 68 } 69 if(tail>head+1) 70 q[m++]=Get_Intersect(deq[head],deq[tail]); 71 } 72 int slove(int mid){ 73 if(n-mid<=2) return 1; 74 for(int i=0;i<n;i++){ 75 seg[i].s=p[i]; 76 seg[i].e=p[(i+mid+1)%n]; 77 seg[i].get_angle(); 78 } 79 HalfPlaneIntersect(seg,n); 80 return zero(Get_Area(q,m)); 81 } 82 int main(){ 83 int t; 84 scanf("%d",&t); 85 while(t--){ 86 scanf("%d",&n); 87 for(int i=0;i<n;i++) 88 scanf("%lf%lf",&p[i].x,&p[i].y); 89 for(int i=1;i<=n/2;i++) swap(p[i],p[n-i]); 90 int ans,low=0,high=n,mid; 91 while(low<=high){ 92 mid=(low+high)/2; 93 if(slove(mid)){ans=mid;high=mid-1;} 94 else low=mid+1; 95 } 96 printf("%d\n",ans); 97 } 98 return 0; 99 }