【UVALive 4642】Malfatti Circles(圆,二分)

给定三角形,求三个两两相切且与三角形的一条边相切的圆的半径。

二分一个半径,可以得出另外两个半径,需要推一推公式(太久了,我忘记了)

#include<cstdio>
#include<cmath>
#define eps (1e-8)
#define sqr(a) (a)*(a)
#define min(a,b) (a)>(b)?(b):(a)
#define dd double
struct point{
    dd x,y,v,a;//点x,y,v为角度,a为边长
}q[10];
dd r0,r1,r2,r3;
int read(){
    int f=0;
    for(int i=0;i<3;i++){
        scanf("%lf%lf",&q[i].x,&q[i].y);
        if(q[i].x||q[i].y) f=1;
    }
    return f;
}
dd make(dd r,dd a,dd h,dd n){
    dd t=r-r/tan(h)/tan(n)+a/tan(n);
    if(t<=eps)return -1;
    return sqr((sqrt(t)-sqrt(r))*tan(n));
}
void solve(){
    dd l=0,r=min(q[0].a*tan(q[0].v),q[2].a*tan(q[2].v));
    while(r-l>eps){
        r0=(l+r)/2;
        r1=make(r0,q[0].a,q[0].v,q[1].v);
        r2=make(r0,q[2].a,q[0].v,q[2].v);
        if(r1<=eps||r2<=eps||r2/tan(q[2].v)+r1/tan(q[1].v)+2*sqrt(r2*r1)-q[1].a<eps)
            r=r0;
        else
            l=r0;
    }
}
int main(){
    while(read())
    {
        for(int i=0;i<3;i++)
            q[i].a=sqrt(sqr(q[(i+1)%3].x-q[i].x)+sqr(q[(i+1)%3].y-q[i].y));//计算边长
        for(int i=0;i<3;i++)
            q[i].v=acos((sqr(q[i].a)+sqr(q[(i+2)%3].a)-sqr(q[(i+1)%3].a))/2/q[i].a/q[(i+2)%3].a)/2;
        solve();
        printf("%lf %lf %lf\n",r0,r1,r2);
    }
}

 

  

posted @ 2016-07-31 16:14  水郁  阅读(324)  评论(0编辑  收藏  举报
……