旋转卡壳是利用一种奇妙的单调性,比较有意思。
枚举一下对角线,旋转卡壳在两边分别找面积最大的三角形。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 4010
using namespace std;
struct yts
{
double x,y;
}a[maxn],s[maxn];
int n,tot,top;
double ans;
yts operator-(yts x,yts y)
{
yts ans;
ans.x=x.x-y.x;ans.y=x.y-y.y;
return ans;
}
double operator*(yts x,yts y)
{
return x.x*y.y-x.y*y.x;
}
double dis(yts x,yts y)
{
return sqrt((y.x-x.x)*(y.x-x.x)+(y.y-x.y)*(y.y-x.y));
}
bool cmp(yts x,yts y)
{
double t=(x-a[1])*(y-a[1]);
if (t==0) return dis(x,a[1])<dis(y,a[1]);
return t>0;
}
void graham()
{
int t=1;
for (int i=2;i<=n;i++)
if (a[i].x<a[t].x || (a[i].x==a[t].x && a[i].y<a[t].y)) t=i;
swap(a[t],a[1]);
sort(a+2,a+n+1,cmp);
top=1;
s[top]=a[1];
for (int i=2;i<=n;i++)
{
while (top>1 && (s[top]-s[top-1])*(a[i]-s[top])<=0) top--;
s[++top]=a[i];
}
}
void solve()
{
for (int i=1;i<=top;i++) s[top+i]=s[i];
ans=0;
for (int i=1;i<=top;i++)
{
int l=i+1,r=i+3;
for (int j=i+2;j<=top;j++)
{
while (l+1<j && (s[l+1]-s[i])*(s[j]-s[i])>(s[l]-s[i])*(s[j]-s[i])) l++;
while (r+1-top<i && (s[j]-s[i])*(s[r+1]-s[i])>(s[j]-s[i])*(s[r]-s[i])) r++;
ans=max(ans,(s[l]-s[i])*(s[j]-s[i])+(s[j]-s[i])*(s[r]-s[i]));
}
}
ans=ans/2.0;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
graham();
solve();
printf("%.3lf\n",ans);
return 0;
}