标签:
题意
给出一正多边形三顶点的坐标,求此正多边形的面积最小值。
分析
为了叙述方便,定义正多边形的单位圆心角u为正多边形的某条边对其外接圆的圆心角(即外接圆的某条弦所对的圆心角)。
(1)多边形的边数未知,但其外接圆是确定的。多边形的外接圆即三个顶点所构成三角形的外接圆。面积最小即边数最少,单位圆心角最大。
(2)设三角形某两边所对的圆心角为a1, a2 (expressed in radians),则最大单位圆心角为
u= gcd(a1, a2, 2PI-a1-a2)。
思路
(1)三点定圆。两线段中垂线交点即为圆心。
若线段AB两端点的坐标分别为 A (x1, y1), B (x2, y2) 则AB的中垂线方程为
2(x1-x2) x + 2(y1-y2) y = (x1^2+y1^2) – (x2^2+y2^2)
此式形式十分对称,便于记忆。
解方程组即的圆心坐标。
(2)求两正实数的最大公约数(gcd)。
(3)求正多边形的面积。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define X first 4 #define Y second 5 #define mp make_pair 6 #define dis2(p) (p.X*p.X+p.Y*p.Y) 7 #define det(i, j) (eq[0][i]*eq[1][j]-eq[0][j]*eq[1][i]) 8 #define ang(p) atan2(p.Y, p.X) 9 #define eps 1e-4 10 #define PI 3.14159263558979323846 11 typedef double db; 12 typedef pair<db, db> P; 13 P p[3]; 14 //make sure that your algorithm is correct 15 db get_ang(P v1, P v2){ 16 return acos((v1.X*v2.X+v1.Y*v2.Y)/dis2(v1)); 17 } 18 P get_center(){ 19 db eq[2][3]; 20 for(int i=0; i<2; i++){ 21 eq[i][0]=2*(p[i].X-p[i+1].X); 22 eq[i][1]=2*(p[i].Y-p[i+1].Y); 23 eq[i][2]=dis2(p[i])-dis2(p[i+1]); 24 } 25 return mp(det(2, 1)/det(0, 1), det(0, 2)/det(0, 1)); 26 } 27 28 P operator - (const P &a, const P &b){ 29 return mp(a.X-b.X, a.Y-b.Y); 30 } 31 32 db gcd(db a, db b){ 33 return b<eps?a:gcd(b, fmod(a, b)); 34 } 35 36 int main(){ 37 //freopen("in", "r", stdin); 38 for(int i=0; i<3; i++) 39 scanf("%lf%lf", &p[i].X, &p[i].Y); 40 P center=get_center(); 41 P v[3]; 42 for(int i=0; i<3; i++) 43 v[i]=p[i]-center; 44 db a1=get_ang(v[0], v[1]); 45 db a2=get_ang(v[0], v[2]); 46 db a3=2*PI-a1-a2; 47 db tmp=gcd(gcd(a1, a2), a3); 48 db res=PI/tmp*dis2(v[1])*sin(tmp); 49 printf("%.8f\n", res); 50 return 0; 51 }
P.S. 这道题还有更简便的解法,不必求外接圆圆心坐标,也不必求圆心角。有下列结论
设题中给出的三点所成三角形的三内角分别为A,B,C (expressed in radians) 则对应u的最大值为
2*gcd(A, B, C)(此式与上面给出的表达式是一致的),A, B, C 可有余弦定理求得,此外还要求三角形外接圆半径R,利用公式 R = abc/4S,a, b, c为三边长,S为面积。
Codeforces 1C Ancient Berland Circus
标签:
原文地址:http://www.cnblogs.com/Patt/p/4691896.html