Codeforces Round #514 (Div. 2) D Nature Reserve(二分)
阿新 • • 發佈:2018-11-08
題意:一個圓與X軸相切,問最小的半徑,使得圓包含所有給定的點。
思路:因為圓是y軸xi相切的,設半徑為R,所以圓心肯定在y=R上,以每個點為圓心作半徑為R的圓與y=R交於l和r,那麼要求的圓的圓心肯定在這個區間,那麼列舉每一個點的l和r,這樣就可以一直縮小l和r的範圍,最後如果l<r,也就是存在這樣一個圓心。所以可以考慮二分列舉R。
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int maxn=100005; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); } int n; struct point { double x,y; }; point p[maxn]; bool check(double k) { double l=-1e18,r=1e18; for(int i=0;i<n;i++) { if(p[i].y>2*k) return 0; double t=sqrt(k-(k-p[i].y))*sqrt(k+(k-p[i].y)); l=max(l,p[i].x-t); r=min(r,p[i].x+t); } return l<r; } int main() { std::ios::sync_with_stdio(false); cin>>n; for(int i=0;i<n;i++) { cin>>p[i].x>>p[i].y; } for(int i=1;i<n;i++) { if(p[i].y*p[0].y<0) { cout<<-1<<endl; return 0; } else p[i].y=fabs(p[i].y); } p[0].y=fabs(p[0].y); double l=0,r=1e18,m,ans; for(int i=0;i<150;i++) { m=(l+r)/2; if(check(m)) { ans=m; r=m; } else l=m; } printf("%.10lf\n",ans); return 0; }