1 面积最大的三角形

https://vjudge.net/contest/647024#problem/A

凸包

https://www.cnblogs.com/aiguona/p/7232243.html

代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int n,top;
struct point
{
	double x,y;
} p[N], s[N];
/*它是点集的最小凸边界。所有点都在
这个多边形的内部或边界上。
给定一个点集,凸包是包含所有这些点的最小凸多边形
这个三角形的一个或多个顶点在凸包的边界上
给定点集,计算凸包可以显著减少点的数量*/

bool cmp(point a, point b)

{
	if (a.x != b.x) return a.x < b.x;
	return a.y < b.y;
	//按照x,y从小到大排序,升序 
	//找到凸包的第一个点 
}


double cross(point a, point b, point c) //叉积
{
	//三角形面积=1/2叉积的绝对值 ,叉积为正,c在ab右侧,a到b转弯到c逆时针,为0三点共线 
	//凸多边形:对于凸多边形上的任意两点 A 和 B,多边形的边界内的点 
//C 必须在AB 的左侧(逆时针方向),保持多边形的凸性。
	return (b.x - a.x) *(c.y- a.y) - (c.x- a.x) * (b.y - a.y);
}


signed main()
{
	scanf("%lld", &n);
	for (int i = 1; i <= n; i++)
		scanf("%lf%lf", &p[i].x,&p[i].y);

	sort(p +1, p +1 + n,cmp);
	
	//下凸包,模拟栈构造,top栈顶,凸包的点数 
	top=0;
	for(int i=1; i<=n; i++)
	{
		while (top > 1 && cross(s[top - 1], s[top], p[i]) <= 0) --top ;
		s[++top] = p[i];
		/*如果叉积值小于或等于 0,说明 p[i] 与当前边的方向不符,可能使当前边向内弯曲,因此需要移除当前边。*/
	}

//上凸包 
	int t = top;
	for (int i = n - 1; i >= 1; i -- )
	{
		while (top > t && cross(s[top - 1], s[top], p[i]) <= 0) --top ;
		s[++top] = p[i];
	}


	n = top - 1;
	double ans = 0;
	double S = 0;
	
	for (int i = 1; i <= n; i++)
	{
		int a = i, b=i +1;
		for (int j = i + 1; j <= n; j++)
		{
			while (cross(s[i], s[j], s[a + 1]) < cross (s[i], s[j], s[a])) a = a % n+1;
			S = max(S, 0.5 * -cross(s[i], s[j], s[a]));
		}
	}
	printf("%.9lf", S);
}

posted on 2024-08-12 21:17  Hoshino1  阅读(8)  评论(0编辑  收藏  举报