计算几何——ICPC Latin American Regional Contests 2019 B

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算几何——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


*/

 

以上是关于计算几何——ICPC Latin American Regional Contests 2019 B的主要内容,如果未能解决你的问题,请参考以下文章

ICPC Latin American Regional 2017-Imperial roads(LCA)

极角排序——ICPC Latin American Regional Contests 2019 D

训练20191007 2017-2018 ACM-ICPC Latin American Regional Programming Contest

2017-2018 ACM-ICPC Latin American Regional Programming Contest

2019-2020 ACM-ICPC Latin American Regional Programming Contest L - Leverage MDT

2017-2018 ACM-ICPC Latin American Regional Programming Contest GYM101889