1C - Ancient Berland Circus(三点确定最小多边形)
原题链接
这题有一个很玄乎的问题,求浮点数的gcd? eps设置精度高了反而错? 参考:博客
题意:给你三个点,问你这包含这三个点构成的所有角相等的多边形最小面积是多少?
思路:根据三角形三个顶点的坐标求得三角形的三边长\(a、b、c\),由海伦公式和正弦定理得半径\(R = abc / (4S)\),再求出外接圆圆心到三角形三个顶点组成的三个圆心角\(∠1、∠2、∠3\)的最大公约数作为正多边形的每一份三角形的内角,将所有三角形加起来即可。思路不难但是容易出现各种问题,比如argcos求角时防止钝角的情况,边长最长的对应的圆心角 应该这样求: 2*PI - 其他两个圆心角。
代码如下
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#include<iomanip>
#define IOS cin.tie(0), ios::sync_with_stdio(false)
#define x first
#define y second
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1010, M = 1e5 + 10, mod = 1e9 + 7;
const double eps = 1e-2;
const double pi = acos(-1);
int sgn(double x) //判断x是否等于0
{
if(fabs(x) < eps) return 0;
else return x < 0 ? -1 : 1;
}
double gcd(double a, double b) //浮点数gcd求法 基于辗转相除法 判断为0函数自定义
{
if(sgn(b) == 0) return a;
if(sgn(a) == 0) return b;
return gcd(b, fmod(a, b)); //fmod用于浮点数取模
}
struct Point{
double x, y;
void input(){ //输入初始化
cin >> x >> y;
}
double distant(Point p) //两点距离
{
double a = (x - p.x);
double b = (y - p.y);
return sqrt(a * a + b * b);
}
};
double angle(double a, double b, double c) //余弦定理求角C
{
return acos((a * a + b * b - c * c) / (2.0 * a * b));
}
int main()
{
IOS;
Point point[3];
for(int i = 0 ; i < 3 ; i ++) point[i].input();
double a = point[0].distant(point[1]);
double b = point[1].distant(point[2]);
double c = point[2].distant(point[0]);
if(a > c) swap(a, c);
if(b > c) swap(b, c);
double p = (a + b + c) / 2.0;
double S = sqrt(p * (p - a) * (p - b) * (p - c));
double r = (a * b * c) / (4.0 * S); //外接圆半径公式
double A = angle(r, r, a);
double B = angle(r, r, b);
double C = 2.0 * pi - A - B;
double avg = gcd(A, gcd(B, C));
double ans = r * r * sin(avg) * pi / avg;
cout << fixed << setprecision(8) << ans << endl;
return 0;
}

浙公网安备 33010602011771号