zoj3806Incircle and Circumcircle

链接

自己的本本没有装画图软件,先借用两张图片。。博客园不让贴源地址。。。

可以想到对于一个确定的外接圆的三角形来说内切圆最大的时候为等边三角形,如下图:

zoj3806Incircle and Circumcircle

确定有合法的解之后,接下来就是去找这个解,解不唯一,可以知道一定可以构造出一个等腰三角形使得满足条件,可以看下图,对于一个确定的外接圆,已知底边和外接圆半径的话,是可以求出三边的,随着底边的缩小和伸长内切圆是先变大后变小,而最大的时候就是上述所说,等边的时候。所以知道了上下界,就可以直接二分底边了,二分的区间就是下图所标区间。

zoj3806Incircle and Circumcircle

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<cmath>

 8 #include<queue>

 9 #include<set>

10 using namespace std;

11 #define N 100000

12 #define LL long long

13 #define INF 0xfffffff

14 const double eps = 1e-10;

15 const double pi = acos(-1.0);

16 const double inf = ~0u>>2;

17 int dcmp(double x)

18 {

19     if(fabs(x)<eps) return 0;

20     return x<0?-1:1;

21 }

22 int cal(double x,double R,double r)

23 {

24     if(dcmp(R*R-x*x)<0) return 0;

25     double a = sqrt(2*R*R+2*R*sqrt(R*R-x*x));

26     double b = a;

27     double c = 2*x;

28     double s = (a+b+c)/2;

29     double tt = (s-a)*(s-b)*(s-c)/s;

30     if(dcmp(tt)<0) return 0;

31     double tr = sqrt(tt);

32     if(dcmp(tr-r)>=0) return 1;

33     return 0;

34 }

35 int main()

36 {

37     double r1,r2;

38     while(scanf("%lf%lf",&r1,&r2)!=EOF)

39     {

40         if(dcmp(2*r1-r2)>0)

41         {

42             puts("NO Solution!");

43             continue;

44         }

45         double rig = sqrt(3.0)*r2,lef = 0,mid;

46         while(rig-lef>eps)

47         {

48             mid = (lef+rig)/2;

49             if(cal(mid,r2,r1))

50                 rig = mid;

51             else lef = mid;

52         }

53        // printf("%f\n",rig);

54         double a = sqrt(2*r2*r2+2*r2*sqrt(r2*r2-rig*rig));

55         double b = a;

56         double c = 2*rig;

57         printf("%.15f %.15f %.15f\n",a,b,c);

58     }

59     return 0;

60 }
View Code

 

你可能感兴趣的:(ZOJ)