参考:传送门
题意:给出一组点,从这些点里面选择三个点构成三角形。求这个三角形面积最大是多少?
题解:凸包
很容易想到三角形的三个点肯定在凸包上面,但是关键怎么找出来三个点。一一枚举肯定超时。
如果固定一条边的话,那么枚举剩下的一个点,在枚举过程中面积肯定有达到极大值后又减小。根据这一特性,可以先固定
一点i,然后让另外两点a,b不断旋转来找三角形面积最大值(a,b事先设定成是点1和点2)。具体步骤如下:
1.枚举i后就将i固定,旋转a,直到找到三角形的最大值。同时更新答案。
2.旋转b,直到找到此时三角形的最大值。同时更新答案。此时即找到三角形一点为i时的最大面积。
3.枚举下一个i,重复1,2步骤
附上代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=50005;
const double eps=1e-10;
struct Point
{
double x, y;
Point(){}
Point(double x_, double y_):x(x_),y(y_){}
} p[maxn], ch[maxn];
typedef Point Vector;
int n;
Vector operator + (Vector a, Vector b) { return Vector(a.x + b.x, a.y + b.y); }
Vector operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y); }
Vector operator * (Vector a, double p) { return Vector(a.x * p, a.y * p); }
Vector operator / (Vector a, double p) { return Vector(a.x / p, a.y / p); }
bool operator < (Point a,Point b)
{
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
int dcmp(double x)
{
if(fabs(x)<eps){
return 0;
}else{
return x<0?-1:1;
}
}
bool operator == (Point a,Point b)
{
return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double dot(Vector a, Vector b) { return a.x * b.x + a.y * b.y; }
double length(Vector a) { return sqrt(dot(a, a)); }
double angle(Vector a, Vector b) { return acos(dot(a, b) / length(a) / length(b)); }
double angle(Vector v) { return atan2(v.y, v.x); }
double cross(Vector a, Vector b) { return a.x * b.y - b.x * a.y; }
double dist(Point p1,Point p2) { return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)); }
int convexHull(Point* p, int n, Point* ch)
{
sort(p, p + n);
int m = 0;
for(int i = 0; i < n; i++) {
while(m > 1 && cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--) {
while(m > k && cross(ch[m-1] - ch[m-2], p[i] - ch[m-2]) <= 0) m--;
ch[m++] = p[i];
}
if(n > 1) m--;
return m;
}
double area(Point a,Point b,Point c){
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
double solve()
{
int m = convexHull(p, n, ch);
//ch[++m] = ch[0];
int a = 1, b = 2;
double res = 0;
for(int i = 0; i < m; i++) {
while(area(ch[i], ch[a], ch[(b+1)%m]) > area(ch[i], ch[a], ch[b]))
b = (b + 1) % m;
res = max(res, area(ch[i], ch[a], ch[b]) / 2.0);
while(area(ch[i], ch[(a+1)%m], ch[b]) > area(ch[i], ch[a], ch[b]))
a = (a + 1) % m;
res = max(res, area(ch[i], ch[a], ch[b]) / 2.0);
}
return res;
}
int main()
{
while(~scanf("%d",&n)&&n!=-1){
for(int i=0;i<n;i++){
scanf("%lf%lf",&p[i].x,&p[i].y);
}
printf("%.2f\n",solve());
}
return 0;
}