题目大意:给出平面上的一些点,求其中四个点的最大四边形的面积。
思路:简单yy一下发现这些点肯定都在凸包上,先求个凸包。然后直接暴力肯定是不行的,我们需要一个O(n^2)的做法,比较简单的想法是枚举最后要求的四边形的一条对线,那么这个四边形就被分割成了两个三角形,剩下两个点与这条线组成的三角形的面积和就是答案。
按照旋转卡壳的思想不难发现,这两个点都是单调的。所以枚举对角线然后扫n圈就可以了。
CODE:
#define _CRT_SECURE_NO_DEPRECATE
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define MAX 10010
#define INF 1e15
using namespace std;
struct Point{
double x,y;
Point(double _,double __):x(_),y(__) {}
Point() {}
bool operator <(const Point &a)const {
return x == a.x ? (y < a.y) : (x < a.x);
}
Point operator -(const Point &a)const {
return Point(x - a.x,y - a.y);
}
void Read() {
scanf("%lf%lf",&x,&y);
}
}point[MAX];
inline double Cross(const Point &p1,const Point &p2)
{
return p1.x * p2.y - p1.y * p2.x;
}
inline double Calc(const Point &p1,const Point &p2)
{
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
int points,top;
Point stack[MAX];
int lines;
inline void Add(const Point &a,int bottom)
{
while(top != bottom && Cross(a - stack[top - 1],stack[top] - stack[top - 1]) >= 0)
--top;
stack[++top] = a;
}
double RotatingCaliper()
{
double re = .0;
for(int i = 0; i < top; ++i) {
int p1 = 1,p2 = 1;
for(int j = i + 1; j < top; ++j) {
while(Cross(stack[p1 + 1] - stack[i],stack[j] - stack[i]) > Cross(stack[p1] - stack[i],stack[j] - stack[i]))
p1 = (p1 + 1) % top;
while(Cross(stack[j] - stack[i],stack[p2 + 1] - stack[i]) > Cross(stack[j] - stack[i],stack[p2] - stack[i]))
p2 = (p2 + 1) % top;
re = max(re,Cross(stack[p1] - stack[i],stack[j] - stack[i]) + Cross(stack[j] - stack[i],stack[p2] - stack[i]));
}
}
return re / 2;
}
int main()
{
cin >> points;
for(int i = 1; i <= points; ++i)
point[i].Read();
sort(point + 1,point + points + 1);
stack[++top] = point[1];
for(int i = 2; i <= points; ++i)
Add(point[i],1);
int temp = top;
for(int i = points - 1; i >= 1; --i)
Add(point[i],temp);
--top;
stack[0] = stack[top];
cout << fixed << setprecision(3) << RotatingCaliper() << endl;
return 0;
}