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;
}
posted @ 2021-04-03 00:46  beatlesss  阅读(118)  评论(0)    收藏  举报