对于一个边数未知的正多边形,给出其上的三个点,求出其可能的最小的面积。
首先对于正多边形其中心肯定是给出三角形的外形。
然后对于三角形的三个角求最大公约数A。
则 N = 2*Pi/A。剩下的就是计算面积了。
做题的时候一直在纠结怎样求边数,然后发现double类型的也能求出最大公约数来。。。
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <algorithm> #define LL long long #define PI (acos(-1)) #define EPS (1e-4) using namespace std; struct P { double x,y; } p[3]; double X_Mul(P a1,P a2,P b1,P b2) { P v1 = {a2.x-a1.x,a2.y-a1.y},v2 = {b2.x-b1.x,b2.y-b1.y}; return v1.x*v2.y - v1.y*v2.x; } P Cal_Segment_Cross_Point(P a1,P a2,P b1,P b2) { double t = X_Mul(b1,b2,b1,a1) / X_Mul(a1,a2,b1,b2); P cp = {a1.x+(a2.x-a1.x)*t,a1.y+(a2.y-a1.y)*t}; return cp; } P Cal_Circle_Center(P a,P b,P c) { P mp1 = {(b.x+a.x)/2,(b.y+a.y)/2},mp2 = {(b.x+c.x)/2,(b.y+c.y)/2}; P v1 = {a.y-b.y,b.x-a.x},v2 = {c.y-b.y,b.x-c.x}; P p1 = {mp1.x+v1.x,mp1.y+v1.y},p2 = {mp2.x+v2.x,mp2.y+v2.y}; return Cal_Segment_Cross_Point(mp1,p1,mp2,p2); } double Cal_Angle(P a1,P a2,P b1,P b2) { P v1 = {a2.x-a1.x,a2.y-a1.y},v2 = {b2.x-b1.x,b2.y-b1.y}; double la2 = v1.x*v1.x + v1.y*v1.y; double lb2 = v2.x*v2.x + v2.y*v2.y; double lc2 = (v2.x-v1.x)*(v2.x-v1.x) + (v2.y-v1.y)*(v2.y-v1.y); return acos( (la2+lb2-lc2)/(2.0*sqrt(la2*lb2)) ); } bool cmp(double a,double b) { return a < b ; } double gcd(double x,double y) { return y>EPS? gcd(y,x-floor(x/y)*y):x; } int main() { int i,n; double a[3],area; for(i = 0; i < 3; ++i) { scanf("%lf %lf",&p[i].x,&p[i].y); } P center = Cal_Circle_Center(p[0],p[1],p[2]); a[0] = Cal_Angle(p[0],p[2],p[0],p[1]); a[1] = Cal_Angle(p[1],p[2],p[1],p[0]); a[2] = Cal_Angle(p[2],p[0],p[2],p[1]); n = PI/gcd(a[0],gcd(a[1],a[2])); double len = sqrt((center.x - p[0].x)*(center.x - p[0].x) + (center.y - p[0].y)*(center.y - p[0].y)); area = n*len*len*sin(PI*2/n)/2; printf("%.8lf\n",area); return 0; }