zoukankan      html  css  js  c++  java
  • 计算几何——ICPC Latin American Regional Contests 2019 B

    /*
    首先想到二分正方形边长到源点的距离mid
    然后判断这个距离是否可行:
        枚举每个点,点到圆心的距离dis
            dis>=mid*sqrt(2),说明这个点对该正方形无影响
             dis<mid,直接返回不可行
            mid<=dis<mid*sqrt(2),说明该正方形需要保持一定的角度区间防止包含这个点
        所有角度区间求交,最后看这个交是否存在即可 
    为了计算方便,直接把所有点投影到第一象限,正方形在第一象限的初始状态设置为等腰直角三角形,且逆时针为正方向
    每个点有一个或两个可行区间,把可行区间排序,离散化后统计一下就行 
    */
    #include<bits/stdc++.h>
    using namespace std;
    #define N 20005
    
    typedef long double db;
    const db eps=1e-8;
    const db sq2=sqrt(2.0);
    const db pi=acos(-1);
    int sign(db k){
        if (k>eps) return 1; else if (k<-eps) return -1; return 0;
    }
    int cmp(db k1,db k2){return sign(k1-k2);}
    int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 
    struct point{
        db x,y;
        point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
        point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
        point operator * (db k1) const{return (point){x*k1,y*k1};}
        point operator / (db k1) const{return (point){x/k1,y/k1};}
        int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
        point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
        point turn90(){return (point){-y,x};}
        bool operator < (const point k1) const{
            int a=cmp(x,k1.x);
            if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
        }
        db abs(){return sqrt(x*x+y*y);}
        db abs2(){return x*x+y*y;}
        db dis(point k1){return ((*this)-k1).abs();}
         point unit(){db w=abs(); return (point){x/w,y/w};}
    };
    int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
    db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
    point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影 
        point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
    }
    struct circle{
        point o; db r;
        int inside(point k){return cmp(r,o.dis(k));}
    };
    vector<point> getCL(circle k1,point k2,point k3){ 
        point k=proj(k2,k3,k1.o); db d=k1.r*k1.r-(k-k1.o).abs2();
        if (sign(d)==-1) return {};
        point del=(k3-k2).unit()*sqrt(max((db)0.0,d)); return {k-del,k+del};
    }
    
    point k1,k2,k3,k4,p[N];
    int n;
    db dis[N],rads[N];
    circle c;
    
    vector<pair<db,int> >s;
    
    int judge(db a){
        s.clear();
        k1=(point){a*sq2,0.0};
        k2=(point){0.0,a*sq2};
        k3=(point){-a*sq2,0.0};
        k4=(point){0.0,-a*sq2};
        for(int i=1;i<=n;i++){
            if(dis[i]<a)return 0;
            if(dis[i]>=a*sq2){
                s.push_back(make_pair(-pi,1));
                s.push_back(make_pair(pi,-1));            
            }
            c.r=dis[i];
            vector<point>v=getCL(c,k2,k1);
            if(v.size()!=0){
                db rad1=atan2(v[0].y,v[0].x);
                db rad2=atan2(v[1].y,v[1].x);
                if(rad1<rad2)swap(rad1,rad2);
                s.push_back(make_pair(rads[i]-rad1,1));
                s.push_back(make_pair(rads[i]-rad2,-1));        
            }
            v=getCL(c,k1,k4);//k1->k4
            if(v.size()!=0){
                db rad1=atan2(v[0].y,v[0].x);
                db rad2=atan2(v[1].y,v[1].x);
                if(rad1<rad2)swap(rad1,rad2);
                s.push_back(make_pair(rads[i]-rad1,1));
                s.push_back(make_pair(rads[i]-rad2,-1));        
            }
        }
        
        sort(s.begin(),s.end());
        int cnt=0;
        for(int i=0;i<s.size();i++){
            cnt+=s[i].second;
            if(cnt==n)return 1;
        }
        return 0;
    }
    
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++)cin>>p[i].x>>p[i].y;
        for(int i=1;i<=n;i++){
            while(sign(p[i].x)<0 || sign(p[i].y)<0)
                p[i]=p[i].turn90();
            dis[i]=sqrt(p[i].x*p[i].x+p[i].y*p[i].y);
            rads[i]=atan2(p[i].y,p[i].x);
        }
        db L=0,R=1e15,mid,ans;
        while(R-L>eps){
            mid=(L+R)/2;
            if(judge(mid))
                ans=mid,L=mid;
            else R=mid; 
        }
        printf("%.4Lf
    ",ans*8);
    }
    /*
    10
    
    966443346 -756724170
    
    -994135047 221603380
    
    -678639837 -178769228
    
    -530862694 752762268
    
    -768046638 -463257882
    
    237914061 265304072
    
    224472503 67786657
    
    -722418124 437150660
    
    280931601 982655876
    
    -100691338 -575414914
    
    100
    -80 58
    -68 -72
    -47 88
    -76 -63
    6 100
    59 -80
    84 54
    93 37
    81 -58
    100 6
    37 93
    100 0
    100 -5
    25 96
    -98 -12
    91 -41
    54 -84
    -87 48
    85 -52
    -87 -48
    -5 100
    59 81
    -72 -67
    48 -86
    -90 42
    -53 85
    -89 -42
    18 -97
    -72 68
    -99 -6
    -36 -92
    95 -29
    -5 -99
    69 -72
    31 -94
    69 73
    -80 -57
    6 -99
    -62 -76
    53 85
    31 95
    0 100
    77 -63
    -24 97
    -42 -89
    -83 -52
    -92 -36
    99 13
    43 -89
    -24 -96
    -83 53
    98 18
    -12 99
    -53 -83
    -99 0
    -41 90
    93 -36
    -62 77
    73 68
    43 90
    -98 19
    97 25
    -57 -79
    -96 -24
    -94 31
    -96 25
    64 77
    77 63
    64 -76
    48 87
    25 -96
    97 -24
    91 42
    36 -92
    99 -12
    13 -98
    -67 73
    19 99
    -99 12
    -18 -98
    88 49
    -99 6
    87 -47
    -76 64
    -92 37
    73 -67
    -47 -87
    95 30
    13 99
    98 -17
    -58 81
    -30 95
    -17 99
    -12 -99
    -36 93
    0 -99
    -94 -30
    81 58
    -97 -18
    -30 -94
    
    
    */
  • 相关阅读:
    selenium WebDriver 清空input的方式
    selenium 获取input输入框中的值的方法
    webdriver报不可见元素异常方法总结
    git踩过的坑
    what's the 数据结构
    算法进阶——贪心与动态规划
    what's the 二叉树
    算法基础——列表排序
    算法基础——列表查找
    Flask项目示例目录
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12676524.html
Copyright © 2011-2022 走看看