计算几何——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\n",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 */