CF第一场比赛的最后一题居然是计算几何.
这道题的考点也是比较多,所以来写一篇题解.
1.平面直角坐标系中两点距离公式:
l
=
(
X
1
−
X
2
)
2
+
(
Y
1
−
Y
2
)
2
l=\sqrt{(X_1-X_2)^2+(Y_1-Y_2)^2}
l=(X1−X2)2+(Y1−Y2)2
2.海伦公式:在知道三边时用于计算三角形面积
S
=
p
(
p
−
a
)
(
p
−
b
)
(
p
−
c
)
S=\sqrt{p(p-a)(p-b)(p-c)}
S=p(p−a)(p−b)(p−c)(其中
a
,
b
,
c
a,b,c
a,b,c为三角形三边,
p
=
a
+
b
+
c
2
p=\frac{a+b+c}{2}
p=2a+b+c)
3.外接圆半径公式:
R
=
a
b
c
4
S
R=\frac{abc}{4S}
R=4Sabc
4.解三角形
(知道三边求角度):
cos
B
=
a
2
+
c
2
−
b
2
2
a
c
\cos B=\frac{a^2+c^2-b^2}{2ac}
cosB=2aca2+c2−b2
cos
A
=
b
2
+
c
2
−
a
2
2
b
c
\cos A=\frac{b^2+c^2-a^2}{2bc}
cosA=2bcb2+c2−a2
cos
C
=
a
2
+
b
2
−
c
2
2
a
b
\cos C=\frac{a^2+b^2-c^2}{2ab}
cosC=2aba2+b2−c2
再将
cos
A
,
cos
B
,
cos
C
\cos A,\cos B,\cos C
cosA,cosB,cosC带入
arccos
(
)
\arccos()
arccos()求出角度
(知道两边一夹角求第三边)
c
=
a
2
+
b
2
−
2
a
b
cos
C
c=\sqrt{a^2+b^2-2ab\cos C}
c=a2+b2−2abcosC
5.欧几里得算法(gcd):看起来和这题没什么关系,具体后面会讲到.
先看一张图:
在图中的A,B,C为给出的点,可以发现这个正多边形与这个三角形的外接圆相同,圆心为O,AO=BO=CO,知道外接圆半径公式后可以求出AO,BO,CO,在会解三角形后可以得出
∠
A
O
B
\angle AOB
∠AOB,
∠
B
O
C
\angle BOC
∠BOC,以及
∠
A
O
C
\angle AOC
∠AOC(指图中大于
18
0
∘
180^\circ
180∘的那个角).可以发现这三个角存在一定的数量关系,及这三个角都可以表示为一个角的整数倍,及相邻黄色半径的夹角,设这个角为
∠
α
\angle\alpha
∠α,于是图中的
∠
A
O
B
=
3
∗
∠
α
\angle AOB=3*\angle\alpha
∠AOB=3∗∠α,
∠
B
O
C
=
2
∗
∠
α
\angle BOC=2*\angle\alpha
∠BOC=2∗∠α,
∠
A
O
C
=
6
∗
∠
α
\angle AOC=6*\angle\alpha
∠AOC=6∗∠α,于是
∠
α
=
g
c
d
(
∠
A
O
B
,
g
c
d
(
∠
B
O
C
,
∠
A
O
C
)
)
\angle\alpha=gcd(\angle AOB,gcd(\angle BOC,\angle AOC))
∠α=gcd(∠AOB,gcd(∠BOC,∠AOC)),角度知道后对于每个小三角形的三边都知道了,三角形个数也知道了,就可以求出总面积了.
#include<bits/stdc++.h>
using namespace std;
const double pi=3.1415926;
double mod(double a,double b)//小数取模
{
return a-(int)(a/b)*b;
}
double gcd(double x,double y)//小数gcd
{
if(y<=0.0001)return x;
return gcd(y,mod(x,y));
}
double x,y,x2,y2,x3,y3;
int main()
{
scanf("%lf%lf%lf%lf%lf%lf",&x,&y,&x2,&y2,&x3,&y3);
//计算三角形三条边长
double a=sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
double b=sqrt((x-x3)*(x-x3)+(y-y3)*(y-y3));
double c=sqrt((x2-x3)*(x2-x3)+(y2-y3)*(y2-y3));
double p=(a+b+c)/2;
double r=(a*b*c)/(4*sqrt(p*(p-a)*(p-b)*(p-c)));//通过r=(abc)/(4s)得出外接圆半径
//分别求出以三条边为低,外接圆半径为腰的三角形的顶角角度
double angle1=acos(1-(a*a)/(2*r*r));
double angle2=acos(1-(b*b)/(2*r*r));
double angle3=2*pi-angle1-angle2;
double angle=gcd(angle1,gcd(angle2,angle3))/pi*180;//题目所示的以正多边形边长为低接圆半径为腰的三角形的顶角角度
double side=sqrt(2*r*r-2*r*r*cos(angle/180*pi));//求出正多边形的边长
double P=(r*2+side)/2;
double S=sqrt(P*(P-r)*(P-r)*(P-side))/*三角形面积*/*(360/angle)/*三角形个数*/;//计算面积
printf("%.6lf",S);//保留6位小数输出
return 0;
}