计算几何——圆卡精度cf1059D

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);
}

猜你喜欢

转载自www.cnblogs.com/zsben991126/p/10948915.html
今日推荐