zoukankan      html  css  js  c++  java
  • UVA1475 Jungle Outpost [半平面交]

    这个题就是一个半平面交加二分,因为敌人每次如果炸k个瞭望塔,那么连续的k个肯定比分散的k个要更优,所以每次二分答案k,将点每隔k个连一条新的线,判断这些新的线有无半平面交即可。

    下面上代码

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define db double
    using namespace std;
    const int M=1e5+10;
    const db eps=1e-7;
    struct point{
        db x,y;
        point(db a=0,db b=0):x(a),y(b){}
        void in(){scanf("%lf%lf",&x,&y);}
    }pp[M];
    
    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,db    b){return point(a.x*b  ,a.y*b  );}
    point operator /(point a,db    b){return point(a.x/b  ,a.y/b  );}
    
    db cross(point a,point b){return a.x*b.y-a.y*b.x;}
    db dot  (point a,point b){return a.x*b.x+a.y*b.y;}
    
    struct line{
        point p,v;
        db ang;
        line(){}
        line(point a,point b):p(a),v(b){ang=atan2(v.y,v.x);}
        bool operator <(line a)const{return ang<a.ang;}
        point getp(db t){return p+v*t;}
    }l[M];
    
    bool onleft(line le,point p){
        return cross(le.v,p-le.p)>0;
    }
    
    point getlinecut(line a,line b){
        point u=a.p-b.p;
        db t=cross(b.v,u)/cross(a.v,b.v);
        return a.getp(t);
    }
    
    int fi,la;
    point p[M];
    line  q[M];
    int n;
    void init(int mid){for(int i=0;i<n;i++){l[i]=line(pp[i],pp[i]-pp[(i+mid+1)%n]);}}
    //二分的mid,每隔mid个连一条线
    bool halfcut(int mid){
        init(mid);
        sort(l,l+n);
        q[fi=la=0]=l[0];
        for(int i=1;i<n;i++){
            while(fi<la&&!onleft(l[i],p[la-1])) --la;
            while(fi<la&&!onleft(l[i],p[fi  ])) ++fi;
            q[++la]=l[i];
            if(fabs(cross(q[la].v,q[la-1].v))<eps){
                --la;if(onleft(q[la],l[i].p)) q[la]=l[i];
            }
            if(fi<la) p[la-1]=getlinecut(q[la],q[la-1]);
        }
        while(fi<la&&!onleft(q[fi],p[la-1])) --la;
        if(la-fi<=1) return 0;return 1;
    }
    
    int le,ri;
    int main()
    {
        while(scanf("%d",&n)==1&&n){
            for(int i=0;i<n;i++) pp[i].in();
            le=1,ri=n;
            while(le<=ri){
                int mid=(le+ri)>>1;
                if(halfcut(mid)) le=mid+1;
                else ri=mid-1;
            }
            printf("%d
    ",le);
        }
        return 0;
    }
  • 相关阅读:
    编译安装redis-3.2.9(latest stable version)
    MySQL之从忘记密码到重置密码
    Linux时间和时区设定
    java.net.UnknownHostException 异常处理(转)
    制作FastDFS的RPM包
    RPM包安装MySQL 5.7.18
    白鹭http请求post
    iframe嵌套页面 跨域
    git 配置 https和ssh 免密码登录 常用操作命令
    php 错误提示开启
  • 原文地址:https://www.cnblogs.com/VictoryCzt/p/10053451.html
Copyright © 2011-2022 走看看