题意:给n (4 ≤ n ≤ 300)个点,求最大四边形面积。
分析:
此题点数太少,n3可过,枚举对角线,求对角线两边最大三角形。
不过还有一个更快的方法 就是凸包+旋转卡壳。
如果凸包只有三个点,则枚举三个点和其他点构成的最大四边形。
如果凸包大于三个点,则直接旋转卡壳求最大四边形。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<cctype>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<iomanip>
#include<sstream>
#include<limits>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll INF = 1e18;
const int maxn = 2e5+10;
const ll MOD = 1000000007;
const double EPS = 1e-10;
const double Pi = acos(-1.0);
#define Vector Point
int dcmp(double x) { return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1); }
struct Point {
double x, y;
Point(const Point& rhs): x(rhs.x), y(rhs.y) { } //拷贝构造函数
Point(double x = 0.0, double y = 0.0): x(x), y(y) { } //构造函数
friend Vector operator + (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); }
friend Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }
friend Vector operator * (const Vector& A, const double& p) { return Vector(A.x*p, A.y*p); }
friend Vector operator / (const Vector& A, const double& p) { return Vector(A.x/p, A.y/p); }
friend bool operator == (const Point& A, const Point& B) { return dcmp(A.x-B.x) == 0 && dcmp(A.y-B.y) == 0; }
friend bool operator < (const Point& A, const Point& B) { return A.x < B.x || (A.x == B.x && A.y < B.y); }
};
double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x; } //叉积
vector<Point> p;
vector<Point> ConvexHull()
{
//预处理,删除重复点
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n = p.size(), m = 0;
vector<Point> res(n+1);
for(int i = 0; i < n; i++) {
while(m > 1 && Cross(res[m-1]-res[m-2], p[i]-res[m-2]) <= 0) m--;
res[m++] = p[i];
}
int k = m;
for(int i = n-2; i >= 0; i--) {
while(m > k && Cross(res[m-1]-res[m-2], p[i]-res[m-2]) <= 0) m--;
res[m++] = p[i];
}
m -= n > 1;
res.resize(m);
return res;
}
double Area(Point p1,Point p2,Point p3) //这里求的面积没*0.5
{
return abs(Cross(p1,p2)+Cross(p2,p3)+Cross(p3,p1));
}
vector<Point> ans;
int main(){
#ifdef LOCAL
freopen("C:\\Users\\lanjiaming\\Desktop\\acm\\in.txt","r",stdin);
//freopen("output.txt","w",stdout);
#endif
//ios_base::sync_with_stdio(0);
int n;
while(scanf("%d",&n)!=EOF)
{
p.clear();ans.clear();
for(int i = 0; i < n; i++)
{
double x,y;
scanf("%lf %lf",&x,&y);
p.push_back(Point(x,y));
}
ans = ConvexHull() ;
double res = 0;
if (ans.size() >= 4)
{
int top = ans.size();
for(int i = 0;i < top;i++) //旋转卡壳
{
int j = (i+2)%top;
int k = (i+1)%top;
int h = (j+1)%top;
while(Area(ans[i],ans[j],ans[k+1]) > Area(ans[i],ans[j],ans[k])) k = (k+1)%top;
double max1 = Area(ans[i],ans[j],ans[k]);
while(Area(ans[i],ans[j],ans[h+1]) > Area(ans[i],ans[j],ans[h])) h = (h+1)%top;
double max2 = Area(ans[i],ans[j],ans[h]);
double ans1 = 0;
while(max1 + max2 > ans1)
{
j = (j+1)%top;
ans1 = max1+max2;
while(Area(ans[i],ans[j],ans[k+1]) > Area(ans[i],ans[j],ans[k])) k = (k+1)%top;
max1 = Area(ans[i],ans[j],ans[k]);
while(Area(ans[i],ans[j],ans[h+1]) > Area(ans[i],ans[j],ans[h])) h = (h+1)%top;
max2 = Area(ans[i],ans[j],ans[h]);
}
res = max(res,ans1);
}
}
else
{
for(int i = 0; i < p.size(); i++)
{
if (p[i] == ans[0] || p[i] == ans[1] || p[i] == ans[2]) continue;
res = max(res,Area(ans[0],ans[1],p[i])+Area(ans[0],ans[2],p[i]));
res = max(res,Area(ans[0],ans[1],p[i])+Area(ans[1],ans[2],p[i]));
res = max(res,Area(ans[1],ans[2],p[i])+Area(ans[0],ans[2],p[i]));
}
}
printf("%.9f\n",res*0.5);
}
return 0;
}