P4166 [SCOI2007]最大土地面积

题意

显然选的四个点是在凸包上的,我们先求出凸包。

考虑枚举对角线\((i,j)\),发现当\(i\)固定,\(j\)沿逆时针旋转时对角线两端的那两个点时单调的,因此用旋转卡壳维护即可。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2010;
const double eps=1e-8;
int n,top;
double ans;
struct Point
{
    double x,y;
    inline double len(){return sqrt(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 double k){return (Point){x*k,y*k};}
    Point operator/(const double k){return (Point){x/k,y/k};}
    double operator*(const Point a)const{return x*a.y-y*a.x;}
    double operator&(const Point a)const{return x*a.x+y*a.y;}
}p[maxn],sta[maxn];
inline int dcmp(double x)
{
	if(fabs(x)<=eps)return 0;
	return x<0?-1:1;
}
inline bool cmp(Point a,Point b){return a.x==b.x?a.y<b.y:a.x<b.x;}
inline Point get(Point a,Point b){return b-a;}
inline void build()
{
	sort(p+1,p+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		while(top>1&&dcmp(get(sta[top-1],sta[top])*get(sta[top],p[i]))<=0)top--;
		sta[++top]=p[i];
	}
	int tmp=top;
	for(int i=n-1;i;i--)
	{
		while(top>tmp&&dcmp(get(sta[top-1],sta[top])*get(sta[top],p[i]))<=0)top--;
		sta[++top]=p[i];
	}	
}
inline void solve()
{
	for(int i=1;i<top;i++)p[i-1]=sta[i];
	for(int i=0;i<top-1;i++)
	{
		int a=i+1,b=i+3;
		for(int j=i+2;j<top-1;j++)
		{
			while((a+1)%top!=j&&dcmp(fabs(get(p[i],p[j])*get(p[i],p[(a+1)%top]))-fabs(get(p[i],p[j])*get(p[i],p[a])))>=0)a=(a+1)%top;
			while((b+1)%top!=i&&dcmp(fabs(get(p[i],p[j])*get(p[i],p[(b+1)%top]))-fabs(get(p[i],p[j])*get(p[i],p[b])))>=0)b=(b+1)%top;
			ans=max(ans,fabs(get(p[i],p[j])*get(p[i],p[a]))+fabs(get(p[i],p[j])*get(p[i],p[b])));
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
	build();solve();
	printf("%.3lf",fabs(ans/2.0));
	return 0;
}
posted @ 2020-01-17 08:59  nofind  阅读(170)  评论(0编辑  收藏  举报