旋转卡(qiǎ)壳(ké)(我还特意去百度一波,但好像意思并不一样,中国文化博大精深啊)。
其实说简单点就是利用了在凸包上的单调性然后一直旋转,还是很好实现的。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#define maxn 2021
using namespace std;
int top,n;
struct P{
double x,y;
P(double a=0,double b=0):x(a),y(b){}
bool operator < (const P& b)const{return x==b.x?y<b.y:x<b.x;}
}p[maxn],s[maxn];
typedef P vec;
vec operator + (vec a,vec b){return vec(a.x+b.x,a.y+b.y);}
vec operator -(P a,P b){return vec(a.x-b.x,a.y-b.y);}
vec operator *(vec a,double p){return vec(a.x*p,a.y*p);}
vec operator /(vec a,double p){return vec(a.x/p,a.y/p);}
double cross(vec a,vec b){return a.x*b.y-a.y*b.x;}
double area2(P a,P b,P c){return fabs(cross(b-a,b-c));}
void make(){
sort(p+1,p+1+n);s[top=1]=p[1];
for(int i=2;i<=n;i++){
while(top>1&&cross(s[top]-s[top-1],p[i]-s[top])<=0)top--;
s[++top]=p[i];
}int m=top;
for(int i=n-1;i>=1;i--){
while(top>m&&cross(s[top]-s[top-1],p[i]-s[top])<=0)top--;
s[++top]=p[i];
}top--;
}
void solve(){
double ans=0;
for(int x=1;x<=top;x++){
int a=x%top+1,b=(x+1)%top+1;
for(int y=x+2;y<=top;y++){
while(a%top+1!=y&&cross(s[a+1]-s[x],s[y]-s[x])>cross(s[a]-s[x],s[y]-s[x]))a=a%top+1;
while(b%top+1!=x&&cross(s[y]-s[x],s[b+1]-s[x])>cross(s[y]-s[x],s[b]-s[x]))b=b%top+1;
ans=max(ans,area2(s[a],s[x],s[y])+area2(s[b],s[x],s[y]));
}
}
printf("%.3lf",ans/2);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
make();solve();
return 0;
}