Link:
很简单的一场比赛打崩了也是菜得令人无话可说……
D:
一眼二分,发现对于固定的半径和点,能包含该点的圆的圆心一定在一个区间内,求出区间判断即可
此题一个重要性质就是圆与$x$轴相切,画出圆心所在直线后就能想到上述贪心了
#include <bits/stdc++.h> using namespace std; #define X first #define Y second #define pb push_back typedef double db; typedef long long ll; typedef pair<db,db> P; const db eps=1e-7; const int MAXN=1e5+10; struct Data{db l,r;int id;}a[MAXN]; int n,cnt1,cnt2;P dat[MAXN]; bool cmp(Data a,Data b) {return a.l<b.l;} db sqr(db x){return 1.0*x*x;} bool cal(db r,int k) { db b=2*dat[k].X; db c=sqr(dat[k].X)+sqr(dat[k].Y-r)-sqr(r); if(sqr(b)-4*c<-eps) return false; a[k].id=k; a[k].l=(b-sqrt(sqr(b)-4*c))/2.0; a[k].r=(b+sqrt(sqr(b)-4*c))/2.0; return true; } bool check(db r) { if(cnt1) r=-r; for(int i=1;i<=n;i++) if(!cal(r,i)) return false; db mn=1e60,mx=-1e60; for(int i=1;i<=n;i++) mn=min(mn,a[i].r),mx=max(mx,a[i].l); return mx<=mn; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lf%lf",&dat[i].X,&dat[i].Y); cnt1+=dat[i].Y<0;cnt2+=dat[i].Y>0; } if(n==1) return printf("%.6lf",dat[1].Y/2.0),0; if(cnt1&&cnt2) return puts("-1"),0; //实数二分最好直接枚举次数,否则精度可能不够 // 也可以相对误差和eps比较 db l=0,r=1e16; for(int i=1;i<=200;i++) { db mid=(l+r)/2.0; if(check(mid)) r=mid; else l=mid; } printf("%.6lf",l); return 0; }