BZOJ1069: [SCOI2007]最大土地面积
1069: [SCOI2007]最大土地面积
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 3548 Solved: 1412
[Submit][Status][Discuss]
Description
在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成
的多边形面积最大。
Input
第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。
Output
最大的多边形面积,答案精确到小数点后3位。
Sample Input
5
0 0
1 0
1 1
0 1
0.5 0.5
0 0
1 0
1 1
0 1
0.5 0.5
Sample Output
1.000
HINT
数据范围 n<=2000, |x|,|y|<=100000
思路{
首先求出凸包.四边形由一条对角线分割成2个三角形,
那么面积最大,就是两个小三角形面积和最大,
那么枚举对角线做旋转卡壳求出对角线两边离对角线最远的点更新答案就可以了.
}
#include<bits/stdc++.h> #define RG register #define il inline #define N 50010 #define db double #define LL long long using namespace std; db Ans=0.00000000000000; struct point{ db x,y; point() {} point(db X,db Y):x(X),y(Y) {} point operator +(const point & a)const{return point(x+a.x,y+a.y);} point operator -(const point & a)const{return point(x-a.x,y-a.y);} point operator *(const db k)const{return point(x*k,y*k);} db operator *(const point & a)const{return x*a.y-y*a.x;} db len(){return sqrt(x*x+y*y);} }p[N],st[N];int n,top; #define eps 1e-6 bool comp(const point & a,const point & b){return a.x==b.x?a.y<b.y:a.x<b.x;} void Graham(){ sort(p+1,p+n+1,comp); for(int i=1;i<=n;++i){ while(top>1&&(p[i]-st[top-1])*(st[top]-st[top-1])>-eps)top--; st[++top]=p[i]; }int NN=top;st[++top]=p[n-1]; for(int i=n-2;i>1;i--){ while(top>NN&&(p[i]-st[top-1])*(st[top]-st[top-1])>-eps)top--; st[++top]=p[i]; }for(int i=1;i<=top;++i)p[i]=st[i]; p[0]=st[top];n=top;return; } void RC(){ for(int i=0;i<n;++i){ int u1=i+1,u2=i+3; for(int j=(i+2);j<n;++j){//枚举对角线 while((u1+1)%n!=i&&(u1+1)%n!=j&&((p[j]-p[i])*(p[u1+1]-p[i]))-((p[j]-p[i])*(p[u1]-p[i]))<eps)u1=(u1+1)%n; while((u2+1)%n!=i&&(u2+1)%n!=j&&((p[j]-p[i])*(p[u2+1]-p[i]))-((p[j]-p[i])*(p[u2]-p[i]))>-eps)u2=(u2+1)%n; Ans=max(Ans,(db)(fabs((p[u1]-p[i])*(p[j]-p[i]))+fabs((p[u2]-p[i])*(p[j]-p[i])))); } } } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%lf%lf",&p[i].x,&p[i].y); Graham();RC();printf("%.3lf",Ans/2); return 0; }