对于一个边数未知的正多边形,给出其上的三个点,求出其可能的最小的面积。
首先对于正多边形其中心肯定是给出三角形的外形。
然后对于三角形的三个角求最大公约数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;
}