習題:Nature Reserve(二分)
阿新 • • 發佈:2020-07-19
題目
思路
我們發現如果直接算半徑不好算
考慮二分半徑
因為圓和\(y=0\)相切
所以圓心一定在直線\(y=r\)上面
考慮每個點和圓心的距離一定小於等於\(r\)
所以針對每一個點,我們都可以求出一個區間,使得圓心和點的距離小於等於\(r\),之後求個交集就行了
這道題精度卡的有點嚴,所以要將求距離的公式化簡一下
程式碼
#include<iostream> #include<cmath> #include<cstdio> using namespace std; const double eps=1e-9; struct node { double x; double y; }a[100005]; int n; int tot; double l=0,r=1e18,mid; double f_abs(double x) { return x<0?-x:x; } bool check(double cnt) { double lef=-100000000,rig=100000000; for(int i=1;i<=n;i++) { if(f_abs(a[i].y-cnt)>cnt) return 0; double L=sqrt(a[i].y*(2*cnt-a[i].y)),R; R=a[i].x+L; L=a[i].x-L; if(rig<L||R<lef) return 0; lef=max(lef,L); rig=min(rig,R); //printf("%.2lf %.2lf\n",lef,rig); } // cout<<endl; return 1; } int main() { ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++) cin>>a[i].x>>a[i].y; for(int i=1;i<=n;i++) { if(a[i].y>0) tot++; } if(!(tot==n||tot==0)) { cout<<"-1"; return 0; } for(int i=1;i<=n;i++) a[i].y=f_abs(a[i].y); for(int i=1;i<=300;i++) { mid=(l+r)/2; if(check(mid)) r=mid; else l=mid; } printf("%.8lf",mid); return 0; }