Codeforces Round #514 (Div. 2)-D. Nature Reserve
阿新 • • 發佈:2018-12-24
思路:題目大意為找與x軸相切並且包含所有點的圓的最小半徑。
一,對半徑r二分,由於圓與x軸相切,圓心(x,y)中y=r,那麼只要看x是否存在即可,對於每一個點找其為圓心,半徑為r時在y=r直線上的範圍,最後看所有的點是否有公共範圍即可
二,對圓心(x,y)中x進行三分,x一定在所有點的x範圍[l,r]內,並且其半徑r的變換曲線是個U型的
Code 1:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long double LD; struct node{ LD x; LD y; }; const int MAX_N=100005; const LD emp=1e-7; int n; node a[MAX_N]; int main() { LD ans=0; scanf("%d",&n); for(int i=0;i<n;++i) { cin>>a[i].x>>a[i].y; if(a[i].y>0) ++ans; else a[i].y=-a[i].y; } if(ans&&ans!=n) ans=-1; LD L=0,R=1e18+5,H; LD h,l,r,li,ri,t; while(R-L>emp&&ans!=-1){ h=(L+R)/2; l=-1e7; r=1e7; bool boo=true; for(int i=0;i<n;++i) { if(h<a[i].y-h){ boo=false; break; } // t=sqrt(h*h-(a[i].y-h)*(a[i].y-h)); //這樣寫精度不夠。。 t=sqrt(h+h-a[i].y)*sqrt(a[i].y); li=a[i].x-t; ri=a[i].x+t; l=max(l,li); r=min(r,ri); if(l>r){ boo=false; break; } } if(boo) R=h; else L=h; } if(ans!=-1){ ans=L; printf("%.10Lf\n",ans); }else printf("-1\n"); return 0; }
Code 2:
#include<iostream> #include<cstdio> #include<cmath> using namespace std; typedef long double LD; struct node{ LD x; LD y; }; const int MAX_N=100005; const LD eps=1e-7; int n; node a[MAX_N]; LD judge(LD x){ LD r=0,tmp; for(int i=0;i<n;++i) { tmp=((x-a[i].x)*(x-a[i].x)+a[i].y*a[i].y)/(2.0*a[i].y); r=max(r,tmp); } return r; } int main() { LD ans=0; scanf("%d",&n); for(int i=0;i<n;++i) { scanf("%Lf%Lf",&a[i].x,&a[i].y); if(a[i].y>0) ++ans; else a[i].y=-a[i].y; } if(ans&&ans!=n) ans=-1; LD l=-1e8,r=1e8,t1,t2; int ss=100; while(ss--&&ans!=-1){ t1=l+(r-l)/3; t2=r-(r-l)/3; if(judge(t1)<=judge(t2)) r=t2; else l=t1; } if(ans!=-1){ ans=judge(l); printf("%Lf\n",ans); }else printf("-1\n"); return 0; }