您的位置:首页 > 编程语言 > PHP开发

【二分】【半平面交】Gym - 101309J - Jungle Outpost

2017-07-13 11:47 483 查看
发现炸毁的瞭望塔必然是连续的,其余下的部分是一个半平面。

二分答案,枚举所有可能的炸毁情况,做个半平面交,如果交出来面积是0,就可以保证不存在安全区域。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
#define EPS 0.0000001
#define N 50010
typedef double db;
const db PI=acos(-1.0);
struct Point{db x,y;};
typedef Point Vector;
Vector operator - (const Point &a,const Point &b){return (Vector){a.x-b.x,a.y-b.y};}
Vector operator * (const Vector &a,const db &k){return (Vector){a.x*k,a.y*k};}
Vector operator + (const Vector &a,const Vector &b){return (Vector){a.x+b.x,a.y+b.y};}
db Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
struct Line
{
Point p; Vector v; db ang;
Line(){}
Line(const Point &a,const Point &b)
{
v=b-a;
p=a;
ang=atan2(v.y,v.x);
if(ang<0) ang+=2.0*PI;
}
};
bool operator < (const Line &a,const Line &b){return a.ang<b.ang;}
bool OnLeft(Line l,Point a){return Cross(l.v,a-l.p)>0;}
Point GetJiaodian(Line a,Line b){return a.p+a.v*(Cross(b.v,a.p-b.p)/Cross(a.v,b.v));}
int n;
Point ps
;
Line q
;
Line ls
;
int nn;
Point a
;
#define INF 10000000000.0
bool BPMJ(int x)
{
int head=1,tail=1;
n=0;
memset(q,0,sizeof(q));
memset(ps,0,sizeof(ps));
for(int i=nn;i>=x+2;--i){
ls[++n]=Line(a[i],a[i-x-1]);
}
for(int i=x+1,j=0;i>=1;++j,--i){
ls[++n]=Line(a[i],a[nn-j]);
}
//    ls[++n]=Line((Point){INF,INF},(Point){-INF,INF});
//    ls[++n]=Line((Point){-INF,INF},(Point){-INF,-INF});
//    ls[++n]=Line((Point){-INF,-INF},(Point){INF,-INF});
//    ls[++n]=Line((Point){INF,-INF},(Point){INF,INF});
sort(ls+1,ls+n+1);
q[1]=ls[1];
for(int i=2;i<=n;++i)
{
while(head<tail&&(!OnLeft(ls[i],ps[tail-1]))) --tail;
while(head<tail&&(!OnLeft(ls[i],ps[head]))) ++head;
q[++tail]=ls[i];
if(fabs(Cross(q[tail].v,q[tail-1].v))<EPS)
{
--tail;
if(OnLeft(q[tail],ls[i].p))
q[tail]=ls[i];
}
if(head<tail)
ps[tail-1]=GetJiaodian(q[tail-1],q[tail]);
}
while(head<tail&&(!OnLeft(q[head],ps[tail-1]))) --tail;
if(tail-head<=1){
return 1;
}
ps[tail]=GetJiaodian(q[tail],q[head]);
return head>tail;
}
int main()
{
freopen("jungle.in","r",stdin);
freopen("jungle.out","w",stdout);
scanf("%d",&nn);
for(int i=1;i<=nn;++i) scanf("%lf%lf",&a[i].x,&a[i].y);
int l=1,r=nn-2;
while(l<r){
int mid=(l+r>>1);
if(BPMJ(mid)){
r=mid;
}
else{
l=mid+1;
}
}
printf("%d\n",l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: