问题:在若干个点中取四个点,求围成的四边形的最大面积。
思路:先求个凸包,n^2 枚举对角线,然后旋转卡壳O(1) 更新左右边界即可。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long LL;
const int INF=0x7fffffff;
const int N =2e3+10;
int n,m,k;
const double esp =1e-6;
int sgn(double x){return x<-esp?-1:x>esp;}
struct Point{
void in(){scanf("%lf%lf",&x,&y);}
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point operator + (Point o){return Point(x+o.x,y+o.y);}
Point operator - (Point o){return Point(x-o.x,y-o.y);}
Point operator * (double len){return Point(x*len,y*len);}
double operator * (Point o){return x*o.y-y*o.x;}
double operator / (Point o){return x*o.x+y*o.y;}
double dis(){return sqrt(x*x+y*y);}
bool operator < (Point o){
if(sgn(y-o.y)==0) return sgn(x-o.x)<0;
return sgn(y-o.y)<0;
}
void out(){
printf("x=%lf,y=%lf\n",x,y);
}
}p[N],cv[N];
double det(Point a,Point b,Point c){
return (b-a)*(c-a);
}
double dot(Point a,Point b,Point c){
return (b-a)/(c-a);
}
Point rot(Point p,double a){
return Point(cos(a)*p.x-sin(a)*p.y,sin(a)*p.x+cos(a)*p.y);
}
const double pi = acos(-1.0);
bool cmp(Point a,Point b){
int dir = sgn(det(p[1],a,b));
if(dir==0) return sgn((a-p[1]).dis()-(b-p[1]).dis())<0;
return dir>0;
}
int Graham(){
for(int i=2;i<=n;i++) if(p[i]<p[1]) swap(p[i],p[1]);
sort(p+2,p+n+1,cmp);
int tot = 2;
cv[1]=p[1],cv[2]=p[2];
p[n+1]=p[1];
for(int i=3;i<=n+1;i++){
while(tot>1 && sgn(det(cv[tot-1],cv[tot],p[i]))<=0) tot--;
cv[++tot]=p[i];
}
return tot-1;
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)==1){
for(int i=1;i<=n;i++) p[i].in();
n = Graham();
// for(int i=1;i<=n;i++) cv[i].out();
double res = 0;
for(int i=1;i<=n;i++){
int r = i,l=i;
for(int j=i+1;j<=n;j++){
Point cur = cv[j]-cv[i];
//cur.out();
Point unit = cv[i]+rot(cur,-pi/2);
// unit.out();
while(sgn(dot(cv[i],unit,cv[r])-dot(cv[i],unit,cv[r%n+1]))<=0) r=r%n+1;
while(sgn(dot(cv[i],unit,cv[l])-dot(cv[i],unit,cv[l%n+1]))>=0) l=l%n+1;
double area = fabs(det(cv[i],cv[j],cv[r]))+fabs(det(cv[i],cv[j],cv[l]));
// printf("start=%d,end=%d,l=%d,r=%d,area=%lf\n",i,j,l,r,area);
res=max(res,area);
}
}
res/=2;
printf("%.3lf\n",res);
}
return 0;
}