【模板】两圆面积交——hdu3264

#include<bits/stdc++.h>
using namespace std;
#define N 2005

typedef double db;
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;}
int cmp(db k1,db k2){return sign(k1-k2);}
struct point{
    db x,y;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    db abs(){return sqrt(x*x+y*y);}
    db dis(point k1){return ((*this)-k1).abs();}
};
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
struct circle{
    point o;db r;
    db area(){return r*r*pi;}
};

circle c[N];
int n;
//两圆关系:5相离,4外切,3相交,2内切,1内含 
int relationcircle(circle k1,circle k2){
    db d=k1.o.dis(k2.o);
    if(sign(d-k1.r-k2.r)>0)return 5;
    if(sign(d-k1.r-k2.r)==0)return 4;
    db l=fabs(k1.r-k2.r);
    if(sign(d-k1.r-k2.r)<0 && sign(d-l)>0)return 3;
    if(sign(d-l)==0)return 2;
    if(sign(d-l)<0)return 1; 
}

db areacircle(circle k1,circle k2){
    int rel=relationcircle(k1,k2);
    if(rel>=4)return 0.0;
    if(rel<=2)return min(k1.area(),k2.area());
    db d=k1.o.dis(k2.o);
    db hf=(k1.r+k2.r+d)/2.0;
    db ss=2*sqrt(hf*(hf-k1.r)*(hf-k2.r)*(hf-d));
    db a1=acos((k1.r*k1.r+d*d-k2.r*k2.r)/(2.0*k1.r*d));
    a1=a1*k1.r*k1.r;
    db a2=acos((k2.r*k2.r+d*d-k1.r*k1.r)/(2.0*k2.r*d));
    a2=a2*k2.r*k2.r;
    return a1+a2-ss;
}

int check(circle k1){//和每个圆求面积交 
    for(int i=1;i<=n;i++)
        if(areacircle(k1,c[i])*2<c[i].area())return 0;
    return 1; 
}

int judge(db r){
    for(int i=1;i<=n;i++){
        circle k1=c[i];
        k1.r=r;
        if(check(k1))return 1;
    }
    return 0;
}

int main(){
    int t;cin>>t;
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r);
        
        db L=0,R=1e10,mid,ans;
        while(R-L>eps){
            mid=(L+R)/2;
            if(judge(mid))
                ans=mid,R=mid;
            else L=mid;
        }
        printf("%.4lf\n",ans);
    }
}

 

posted on 2020-02-22 11:58  zsben  阅读(181)  评论(0编辑  收藏  举报

导航