●POJ 2187 Beauty Contest

 

题链:

http://poj.org/problem?id=2187

题解:

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

一个求凸包直径的裸题,旋转卡壳入门用的。

代码:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 50050
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);}
bool operator == (Point A,Point B){return 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];
double GL2(Vector A){//Get_Length^2
	return A*A;
}
double DA(Point P,Point P1,Point P2){//Directed_Area
	return (P-P1)^(P-P2);
}
int Andrew(int dnt){
	int cnt=0,k;
	sort(D,D+dnt);
	dnt=unique(D,D+dnt)-D;
	for(int i=0;i<dnt;i++){
		while(cnt>1&&sign((C[cnt-1]-C[cnt-2])^(D[i]-C[cnt-2]))<=0) cnt--;
		C[cnt++]=D[i];
	} k=cnt;
	for(int i=dnt-2;i>=0;i--){
		while(cnt>k&&sign((C[cnt-1]-C[cnt-2])^(D[i]-C[cnt-2]))<=0) cnt--;
		C[cnt++]=D[i];
	}
	return cnt-(dnt>1?1:0);
}
double RC_GD(int hnt){//Rotating_Calipers_Get_Diameter
	if(hnt==1) return 0;
	if(hnt==2) return GL2(C[1]-C[0]);
	double Di=0; int j=0; C[hnt]=C[0];
	for(int i=0;i<hnt;i++){
		while(sign(DA(C[j],C[i],C[i+1])-DA(C[j+1],C[i],C[i+1])<=0)) j=(j+1)%hnt;
		Di=max(Di,GL2(C[j]-C[i])); Di=max(Di,GL2(C[j]-C[i+1]));
	}
	return Di;
}
int main(){
	int N; scanf("%d",&N);
	for(int i=0;i<N;i++) 
		D[i].Read();
	printf("%d",(int)RC_GD(Andrew(N)));
	return 0;
}

  

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