UVA1475 Jungle Outpost(半平面交)
原题链接:UVA1475
分析:首先要知道这个结论:敌人最优的炸法是连续轰炸,而不是分散火力。
我发现网上大多数博客都没有证明这个结论,来给大家一个简单的证明好了:
如图所示,我们先轰炸A点得到三角形AEF,接下来如果轰炸B点得到三角形BEF,如果轰炸C点得到三角形BCD
那么现在问题转化为证明BEF的面积大于BCD的面积。
因为B与E隔F,A两个点,而B与D之隔只有点C,所以BE会倾向于大于BD,同理高h1也会倾向于大于h2,
所以在这个六边形上枚举两个相邻的点轰炸必定最优,在n条边多边形连续轰炸m个点也会比分散轰炸更优,证完了。。。
有了这个结论问题就简单多了,我们只要结合半平面交二分答案就好了,下面是AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 double eps=1e-15; 5 double pi=acos(-1); 6 struct Point{ 7 double x,y; 8 Point(double x=0,double y=0):x(x),y(y){} 9 }; 10 typedef Point Vector; 11 Vector operator + (Vector A,Vector B){return Vector(A.x+B.x,A.y+B.y);} 12 Vector operator - (Vector A,Vector B){return Vector(A.x-B.x,A.y-B.y);} 13 Vector operator * (Vector A,double B){return Vector(A.x*B,A.y*B);} 14 Vector operator / (Vector A,double B){return Vector(A.x/B,A.y/B);} 15 int dcmp(double x){ 16 if(fabs(x)<eps)return 0; 17 else return x<0?-1:1; 18 } 19 bool operator < (const Point &a,const Point &b){ 20 return dcmp(a.x-b.x)<0||(dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)<0); 21 } 22 bool operator == (const Point &a,const Point &b){ 23 return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; 24 } 25 double Cross(Vector A,Vector B){ 26 return A.x*B.y-A.y*B.x; 27 } 28 double Dot(Vector A,Vector B){ 29 return A.x*B.x+A.y*B.y; 30 } 31 int dis(Point A,Point B){ 32 return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y*B.y); 33 } 34 Vector Rotate(Vector A,double rad){ 35 return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad)); 36 } 37 double len(Vector v) 38 { 39 return sqrt(Dot(v,v)); 40 } 41 Vector normal(Vector v) 42 { 43 Vector u=(Vector){-v.y,v.x}; 44 return u/len(u); 45 } 46 void readp(Point &A){ 47 scanf("%lf%lf",&A.x,&A.y); 48 } 49 struct Line{ 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 return ang<L.ang; 57 } 58 }; 59 bool onleft(Line L,Point p){ 60 return Cross(L.v,p-L.p)>0; 61 } 62 Point getintersection(Line a,Line b){ 63 Vector u=a.p-b.p; 64 double t=Cross(b.v,u)/Cross(a.v,b.v); 65 return a.p+a.v*t; 66 } 67 int bpmj(Line *L,int n,Point *poly){ 68 sort(L,L+n); 69 int first,last; 70 Point *p=new Point[n]; 71 Line *q=new Line[n]; 72 q[first=last=0]=L[0]; 73 for(int i=1;i<n;i++){ 74 while(first<last&&!onleft(L[i],p[last-1]))last--; 75 while(first<last&&!onleft(L[i],p[first]))first++; 76 q[++last]=L[i]; 77 if(fabs(Cross(q[last].v,q[last-1].v))<eps){ 78 last--; 79 if(onleft(q[last],L[i].p))q[last]=L[i]; 80 } 81 if(first<last)p[last-1]=getintersection(q[last-1],q[last]); 82 } 83 while(first<last&&!onleft(q[first],p[last-1]))last--; 84 if(last-first<=1)return 0; 85 p[last]=getintersection(q[last],q[first]); 86 int m=0; 87 for(int i=first;i<=last;i++)poly[m++]=p[i]; 88 return m; 89 } 90 int n; 91 const int maxn=50005; 92 Point p[maxn],poly[maxn]; 93 Line L[maxn]; 94 int main(){ 95 while(~scanf("%d",&n)){ 96 for(int i=0;i<n;i++){ 97 readp(p[i]); 98 } 99 int l=1,r=n+1; 100 while(l<r){ 101 int m=(l+r)/2; 102 int cnt=0; 103 for(int i=0;i<n;i++){ 104 int j=(i+m+1)%n; 105 Vector v=p[i]-p[j]; 106 L[cnt++]=Line(p[i],v); 107 } 108 if(!bpmj(L,cnt,poly))r=m; 109 else l=m+1; 110 } 111 printf("%d\n",l); 112 } 113 }