[BZOJ1069]SCOI2007最大土地面积|凸包|旋转卡壳

    这大概才是真正的第一题计算几何了。。首先这四个点肯定在凸包上,所以求出凸包,之后枚举四边形的对角线AB,凸包求出来之后点是按逆时针排序的,不妨设B在A的逆时针方向,那么就在A逆时针转到B的点之间取一个C点使三角形ABC面积最大,这个用叉积很方便,再在B逆时针转到A的点之间曲一个D使三角形ABD面积最大,现在ABCD就是以AB为对角线面积的最大值。。


当A固定B逆时针转的时候C,D都是逆时针转的,所以这有点像旋转卡壳,每一个点只需要O(N)就可以枚举完答案,所以总复杂度是O(N^2)。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 2005
#define t1 st[top]
#define t2 st[top-1]
using namespace std;
struct point{
	double x,y;
	point(){}
	point(double x,double y):x(x),y(y){}
} a[N],st[N];
int top,end,i,n;
point operator-(point a,point b){return point(a.x-b.x,a.y-b.y);}
double operator*(point a,point b){return a.x*b.y-a.y*b.x;}
bool cmp(point a,point b)
{
	if (a.x!=b.x) return a.x<b.x;else return a.y<b.y;
}
void push(point x)
{
	while (top>=end+2&&(t1-t2)*(x-t1)<=0) top--;
	st[++top]=x;
}
void graham()
{
	end=0;top=0;
	sort(a+1,a+1+n,cmp);
	for (int i=1;i<=n;i++) push(a[i]);
	end=top-1;
	for (int i=n-1;i;i--) push(a[i]);
	top--;
}
int next(int i){return i%top+1;}
double sRC()
{
	double ans=0;
	int l,r;
	for (int i=1;i<=top;i++)
	{
		l=next(i);r=next(i+2);
		for (int j=i+2;j<=top;j++)
		{
			if (r==j)r=next(r);
			while (next(l)!=j&&(st[l]-st[i])*(st[j]-st[i])<(st[next(l)]-st[i])*(st[j]-st[i])) l=next(l);
			while (next(r)!=i&&(st[j]-st[i])*(st[r]-st[i])<(st[j]-st[i])*(st[next(r)]-st[i])) r=next(r);
			ans=max(ans,(st[l]-st[i])*(st[j]-st[i])+(st[j]-st[i])*(st[r]-st[i]));
		}
	}
	return ans;
}
int main()
{
	freopen("1069.in","r",stdin);
	scanf("%d",&n);
	for (i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
	graham();
	printf("%.3lf\n",sRC()/2);
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章