double 在1e17以后就不能顾及小数,所以用一下加精度的技巧
sqrt(r*r-d*d)=sqrt(r+d)*sqrt(r-d)
遇到误差在几位以内的注意要修改二分的精度,用最大的数据去乘以精度即可
#include<bits/stdc++.h> using namespace std;const double esp = 1e-7; const double inf = 1e14;double sgn(double x){if(fabs(x)<esp)return 0;if(x<0)return -1;return 1; } struct Point {double x,y;Point(){}Point (double x,double y):x(x),y(y){}double distance(Point p){return hypot(x-p.x,y-p.y);} }; struct circle{Point p;double r;circle(){}circle(Point p,double r):p(p),r(r){}int relation(Point b){double dst=b.distance(p);if(sgn(dst-r)<0)return 2;else if(sgn(dst-r)==0)return 1;return 0;}int relationline(double y){//直线只有y=b double dst=fabs(y-p.y);if(sgn(dst-r)<0)return 2;else if(sgn(dst-r)==0)return 1;return 0;}int pointcrossline(double y,Point &p1,Point &p2){if(!(*this).relationline(y))return 0;Point a=Point(p.x,y);double d=fabs(p.y-y);d=sqrt(r*r-d*d);if(sgn(d)==0){p1=a,p2=a;return 1;}p1=Point(a.x-d,y);p2=Point(a.x+d,y);return 2;} };#define maxn 100005 Point p[maxn]; int n;//判断半径r是否可行,每个点画个圆和y=r相交,维护L,R即可 int judge(long double r){long double L=-1e15,R=1e15;for(int i=1;i<=n;i++){if(r*2-p[i].y<0)return 0; long double d=fabs(r-p[i].y);d=sqrt(r+d)*sqrt(r-d);//这里要扩大精度 L=max(L,p[i].x-d);R=min(R,p[i].x+d); }return L<=R; }int main(){cin>>n;int flag0=0,flag1=0;double Min=inf,Max=-inf,M=-inf;for(int i=1;i<=n;i++){ scanf("%lf%lf",&p[i].x,&p[i].y);if(p[i].y<0) flag0=1;else flag1=1;Min=min(Min,p[i].x);Max=max(Max,p[i].x);M=max(M,fabs(p[i].y));} if(flag0 && flag1){puts("-1");return 0;}if(flag0){for(int i=1;i<=n;i++)p[i].y *= -1;}double l=0,r=inf,mid,ans=-1,x=max((Max-Min),M)*esp;while(x<r-l){mid=(l+r)/2;if(judge(mid))ans=mid,r=mid;else l=mid;}printf("%.7lf",ans); }