Description
在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成
的多边形面积最大。
Input
第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。
Output
最大的多边形面积,答案精确到小数点后3位。
选的点都在凸包上且对角线上的点相距最远,所以可以顺序枚举凸包上的点并旋转卡壳
#include<cstdio> #include<cmath> #include<algorithm> typedef long double ld; const ld _0=1e-7; struct vec{ld x,y;}; vec operator+(vec a,vec b){return (vec){a.x+b.x,a.y+b.y};} vec operator-(vec a,vec b){return (vec){a.x-b.x,a.y-b.y};} vec operator*(vec a,ld x){return (vec){a.x*x,a.y*x};} ld operator*(vec a,vec b){return a.x*b.y-a.y*b.x;} bool operator<(vec a,vec b){return a*b>0;} ld abs(vec a){return sqrt(a.x*a.x+a.y*a.y);} int n,p,p1,p2,p3; vec vs[10010],ps[20010],m; ld ans=0; int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ double x,y; scanf("%lf%lf",&x,&y); vs[i]=(vec){x,y}; } for(int i=1;i<n;i++)if(vs[i].x<vs[p].x||vs[i].x==vs[p].x&&vs[i].y<vs[p].y)p=i; m=vs[p]; for(int i=0;i<n;i++){ vs[i]=vs[i]-m; if(abs(vs[i])<_0)vs[i--]=vs[--n]; } std::sort(vs,vs+n); ps[0]=(vec){0,0}; ps[p=1]=vs[0]; for(int i=1;i<n;i++){ while(p&&(ps[p]-ps[p-1])*(vs[i]-ps[p])<_0)--p; ps[++p]=vs[i]; } n=p+1; for(int i=0;i<=n;i++)ps[i+n]=ps[i]; int n0=n; n=n*2+1; for(p=0,p1=p2=p3=1;p<n0;p++){ while(p2<n&&abs(ps[p2+1]-ps[p])>abs(ps[p2]-ps[p]))++p2; if(p2>p3)p3=p2; vec w=ps[p2]-ps[p]; while(p1<n&&w*(ps[p1+1]-ps[p])<w*(ps[p1]-ps[p]))++p1; while(p3<n&&w*(ps[p3+1]-ps[p])>w*(ps[p3]-ps[p]))++p3; ld S=w*(ps[p3]-ps[p1]); if(S>ans)ans=S; } printf("%.3lf\n",(double)ans*.5); return 0; }