首页 > 代码库 > ZOJ 3806 Incircle and Circumcircle 【几何】【special judge】

ZOJ 3806 Incircle and Circumcircle 【几何】【special judge】

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3806

题目大意:给一个三角形的外接圆半径以及内切圆半径,求满足给出条件的三角形的三条边。

题目给出的样例有点坑.......容易误导人

Sample Input

1 2
2 5
9 9

Sample Ouput

3.464101615137754587 3.464101615137754587 3.464101615137754587
6 8 10
NO Solution!

给出的2和5的例子的时候其答案给出的是三个整数。所以会有点误导。

最开始看见题目的时候被样例误导了,一直没有什么思路,后来在纸上画了很久发现了一个特例。

YY给出的内切圆和外切圆的圆心是在一个直线上面的,然后是可以根据正弦定理以及一系列的变形得到长度x和角度α之间的关系。




然后数学公式可以得出:角度α和x的公式为

x =( 1 + 1 / sin(α) )/ (2 - 2*sin(α)*sin(α))

根据公式二分sin(α) 

sin(α)的取值范围是0~1,比较与输入x 的大小,重新确定上界下界。(此函数是一个递增的)

求得sin(α)后可以根据x的大小以及α角度一些关系得到三角形的三条边。

注意变换之后默认的内切圆半径是1,故求得的三角形三边要乘于R/r

#include<iostream>
#include<math.h>
#include<cstring>
#include<stdio.h>
#include<algorithm>
using namespace std;


#define eps 1e-11
double er(double x)
{
    double l = 0, r = 1, mid;
    while(l<r){
        mid = (l+r)/2;
        //printf("%.9lf %.9lf\n",l,r);
        double temp = (1.0+1.0/mid)/(2.0-2.0*(mid*mid));
        if(temp-x>eps)   l = mid;
        else if(temp+eps<x) r = mid;
        else break;
    }
    //printf("%.13lf\n",mid);
    return mid;
}


int main ()
{
    double n,m;
    while(~scanf("%lf %lf",&n,&m)){
        double bi=m/n;
        if((bi-2)<-eps) {printf("NO Solution!\n");continue;}
        double sinx=er(bi);
        double cosx=sqrt(1-sinx*sinx);
        double y = (1.0 + 1.0/sinx)/cosx;
        double t = (1.0+sinx)/cosx;

        printf("%.18lf %.18lf %.18lf\n",y*n,y*n,2*t*n);

    }
}
忽略我的函数名称定义以及...... 出现的一个er(bi)   ........

ZOJ 3806 Incircle and Circumcircle 【几何】【special judge】