和吴昊一起玩推理 Round 8 —— 计算几何一系列(C)—— 圆上知道一点求另外两点组成一个周长最长的三角形(HDOJ 1700)

 

 Source: HDOJ 1700

 

【数学证明】 

  设R是圆半径,A,B,C是三角形的角,由正弦定理得a/sinA =b/sinB=c/sinC=2R
故a+b+c=2R(sinA+sinB+sinC),当R确定求周长a+b+c最大,归结为求sinA+sinB+sinC的最大.
设Y=sinA+sinB+sinC,先固定角A,
Y=sinA+sinB+sinC=sinA+2sin((B+C)/2)cos((B-C)/2)
=sinA+2cos(A/2)cos((B-C)/2)
因为A是定值,故只有B=C时,Y才有最大值,同理分别再固定角B,C,则当C=A,A=B时,
Y才有最大值,故A=B=C=60时,Y值最大,即周长a+b+c最大.
也即同圆或等圆中周长最大的三角形是等边三角形.

 

 
  1 【一般方法】
  2 
  3  
  4 
  5   #include<stdio.h>
  6 #include<math.h>
  7  #define pi acos(-1.0)
  8  #define epx 0.0005
  9  int main()
 10 {
 11   int t;
 12   double x1,y1,x2,y2,x3,y3,a,r,b;
 13  scanf( " %d ",&t);
 14   while(t--&&scanf( " %lf%lf ",&x1,&y1))
 15  {
 16    r=sqrt(x1*x1+y1*y1);
 17     if(x1!= 0&&y1!= 0)
 18    {
 19      if(x1< 0&&y1< 0)a=pi+atan(y1/x1);
 20      else  if(x1< 0&&y1> 0)a=pi+atan(y1/x1);
 21      else a=atan(y1/x1);
 22    }
 23     else  if(x1== 0&&y1!= 0)
 24    {
 25        if(y1> 0)a=pi/ 2;
 26        else a=-pi/ 2;
 27    }
 28     else  if(x1!= 0&&y1== 0)
 29    {
 30      if(x1> 0)a= 0;
 31      else a=pi;
 32    }
 33    b= 2*pi/ 3+a;
 34    x2=cos(b)*r;y2=sin(b)*r;
 35    x3=-(x1+x2);y3=-(y1+y2);
 36     if(fabs(y2-y3)<epx)
 37    {
 38      if(x2<x3)printf( " %.3lf %.3lf %.3lf %.3lf\n ",x2,y2,x3,y3);
 39    else printf( " %.3lf %.3lf %.3lf %.3lf\n ",x3,y3,x2,y2);  
 40    }
 41     else
 42    {
 43       if(y2<y3)printf( " %.3lf %.3lf %.3lf %.3lf\n ",x2,y2,x3,y3);
 44    else printf( " %.3lf %.3lf %.3lf %.3lf\n ",x3,y3,x2,y2);
 45    }
 46  }
 47 }
 48 
 49  
 50 【复平面方法】
 51  
 52 #include<stdio.h>
 53 #include<math.h>
 54  #define s sqrt(3.0)
 55  #define epx 0.0005
 56  int main()
 57 {
 58   int t;
 59   double x1,y1,x2,y2,x3,y3,a,r,b;
 60  scanf( " %d ",&t);
 61   while(t--&&scanf( " %lf%lf ",&x1,&y1))
 62  {
 63    x2=-(x1+s*y1)/ 2;
 64    y2=(s*x1-y1)/ 2;
 65    x3=-(x1+x2);y3=-(y1+y2);
 66     if(fabs(y2-y3)<epx)
 67    {
 68      if(x2<x3)printf( " %.3lf %.3lf %.3lf %.3lf\n ",x2,y2,x3,y3);
 69    else printf( " %.3lf %.3lf %.3lf %.3lf\n ",x3,y3,x2,y2);  
 70    }
 71     else
 72    {
 73       if(y2<y3)printf( " %.3lf %.3lf %.3lf %.3lf\n ",x2,y2,x3,y3);
 74    else printf( " %.3lf %.3lf %.3lf %.3lf\n ",x3,y3,x2,y2);
 75    }
 76  }
 77 }
 78 
 79 【向量法】
 80 
 81  设 P(x,y),一个方程是pow(x, 2)+pow(y, 2)=pow(r, 2);另一个方程是根据向量知识,向量的夹角公式得到方程。因为圆心角夹角 为120度,已知一个向量(即一个点作标),所以COS(2PI/ 3)=a*b/|a|*|b|;(a,b为向量);已知角和a向量,就可求b向量 b(x,y).由方程组可求得(x,y);最后得到的是一元二次方程组,可得到两个解,即为两个点的作标。
 82 
 83 #include<stdio.h>
 84 #include<math.h>
 85  struct Point
 86 {
 87  double x;
 88  double y;
 89 };
 90  int main()
 91 {
 92 Point p1,p2,p3;
 93  double a,b,c,r,delta;
 94  int t,i;
 95  for (;scanf( " %d ",&t)!=EOF;)
 96 {
 97  for (i= 0;i<t;i++)
 98 {
 99 scanf( " %lf%lf ",&p1.x,&p1.y);
100 r=sqrt(p1.x*p1.x+p1.y*p1.y);
101 a=p1.x*p1.x+p1.y*p1.y;
102 b=p1.y*r*r;
103 c=(-p1.x*p1.x*r*r+r*r*r*r/ 4);
104 delta=b*b- 4*a*c;
105 p2.y=(- 1*b-sqrt(delta))/( 2*a);
106 p3.y=(- 1*b+sqrt(delta))/( 2*a);
107  if(p1.x== 0)
108 {
109 p2.x=-sqrt(r*r-p2.y*p2.y);
110 p3.x=sqrt(r*r-p2.y*p2.y);
111 }
112  else
113 {
114 p2.x=(- 1*r*r/ 2-p1.y*p2.y)/p1.x;
115 p3.x=(- 1*r*r/ 2-p1.y*p3.y)/p1.x;
116 }
117 
118 printf( " %.3lf %.3lf %.3lf %.3lf\n ",p2.x,p2.y,p3.x,p3.y);
119 }
120 }
121  return  0;
122 }
123 【方程组法】
124 
125 已知一个以( 00)为圆心的圆和圆上的一点(x0,y0)求圆上的另外两点(x1,y1,)(x2,y2),使得向量(x1,y1)(x2,y2)和(x0,y0)各个向量两两之间夹角为120度
126 
127 此题主要用到向量的叉乘和点乘列出两个二元一次方程组
128 
129  1.
130 
131 (x0,y0)X (x1,y1) = sin( 120)*R^ 2 (r为圆的半径)
132 
133 (x0,y0) * (x1,y1) = cos( 120)*R^ 2
134 
135 结果为:
136 
137 x1=b*x0-a*y0; a=sin120
138 y1=b*y0+a*x0; b=cos120;
139 
140  2.
141 
142 (x0,y0)X (x2,y2) = -sin( 120)*R^ 2 (r为圆的半径)
143 
144 (x0,y0) * (x2,y2) = cos( 120)*R^ 2
145 
146 注:题目假设向量(x1,y1)在向量(x0,y0)逆时针方向 故叉乘结果为正值
147 
148 (x2,y2)于(x0,y0)的顺时针方向 故叉乘结果为负值
149 
150 #include <stdlib.h>
151 #include <stdio.h>
152 #include <math.h>
153  int main( int argc,  char** argv) {
154 
155 
156  double a,b,sinx,cosx,x0,y0,x1,y1,x2,y2;
157  int t;
158 
159 a=sinx=sqrt( 3.0)/ 2;
160 b=cosx=- 0.5;
161 scanf( " %d ",&t);
162  while(t--)
163 {
164 scanf( " %lf%lf ",&x0,&y0);
165 
166 x1=b*x0-a*y0;
167 y1=b*y0+a*x0;
168 x2=b*x0+a*y0;
169 y2=b*y0-a*x0;
170  if(y1<y2||((abs(y1-y2)< 0.005)&&x1<x2))
171 {
172 printf( " %.3lf %.3lf %.3lf %.3lf\n ",x1,y1,x2,y2);
173 }
174  else
175 printf( " %.3lf %.3lf %.3lf %.3lf\n ",x2,y2,x1,y1);
176 
177 }
178 
179  return (EXIT_SUCCESS);
180 }

你可能感兴趣的:(round)