●BZOJ 1069 [SCOI2007]最大土地面积

题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=1069

题解:

计算几何,凸包,旋转卡壳

其实和这个题差不多,POJ 2079 Triangle

把四边形看出两个三角形就好了。

复杂度$O(N^2)$

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 2050
using namespace std;
const double eps=1e-8;
int sign(double x){
	if(fabs(x)<=eps) return 0;
	return x<0?-1:1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0):x(_x),y(_y){}
	void Read(){scanf("%lf%lf",&x,&y);}
};
typedef Point Vector;
bool operator < (Point A,Point B){return sign(A.x-B.x)<0||(sign(A.x-B.x)==0&&sign(A.y-B.y)<0);}
Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);}
double operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;}
double operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;}
Point D[MAXN],C[MAXN];
int Andrew(int dnt){
	int cnt=0,k;
	sort(D+1,D+dnt+1);
	for(int i=1;i<=dnt;i++){
		while(cnt>1&&sign((C[cnt]-C[cnt-1])^(D[i]-C[cnt-1]))<=0) cnt--;
		C[++cnt]=D[i];
	} k=cnt;
	for(int i=dnt-1;i>=1;i--){
		while(cnt>k&&sign((C[cnt]-C[cnt-1])^(D[i]-C[cnt-1]))<=0) cnt--;
		C[++cnt]=D[i];
	}
	return cnt-(dnt>1);
}
double DA(Point P,Point P1,Point P2){//Directed_Area
	return fabs((P1-P)^(P2-P))/2;
}
double RC(int cnt){//Rotating_Calipers
	double S=0; C[cnt+1]=C[1];
	for(int i=1,j,k1,k2;i<=cnt;i++){
		k1=i%cnt+1; j=k1%cnt+1; k2=j%cnt+1;
		for(int cj=1;cj<=cnt-3;cj++,j=j%cnt+1){
			while(sign(DA(C[k1],C[i],C[j])-DA(C[k1+1],C[i],C[j]))<=0) k1=k1%cnt+1;
			while(sign(DA(C[k2],C[i],C[j])-DA(C[k2+1],C[i],C[j]))<=0) k2=k2%cnt+1;
			S=max(S,DA(C[k1],C[i],C[j])+DA(C[k2],C[i],C[j]));
		}
	}
	return S;
}
int main(){
	int n; scanf("%d",&n);
	for(int i=1;i<=n;i++) D[i].Read();
	printf("%.3lf",RC(Andrew(n)));
	return 0;
}

  

posted @ 2018-01-07 11:50  *ZJ  阅读(184)  评论(0编辑  收藏  举报