POJ-2187___Beauty Contest —— 旋转卡壳 + 凸包直径

题目链接:点我啊╭(╯^╰)╮

题目大意:

    求二维平面内最远点距离的平方

解题思路:

    最远点的距离即凸包的直径
    枚举凸包的边,距离该边最远的点组成的也是最大三角形面积
    根据三角形面积(对锺点)的单峰性质,可以快速找到最远点
    枚举下一条边时,最远点只会继续逆时针旋转
在这里插入图片描述

核心:旋转卡壳

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
const double eps = 1e-6;
const int maxn = 1e5 + 10;
int n;
struct point {
	double x, y;
	point() {}
	point(double X, double Y) {
		x = X, y = Y;
	}
	point operator - (const point &A) {
		return point(x-A.x, y-A.y);
	}
	bool operator < (const point &A)const {
		if(x == A.x) return y < A.y;
		return x < A.x;
	}
} a[maxn], pa[maxn];

int dcmp(double x) {
	if(fabs(x) < eps) return 0;
	return x < 0 ? -1 : 1;
}
double cross(point A, point B) {	//	叉积
	return A.x*B.y - B.x*A.y;
}
double xmult(point a, point b, point c) {
	return cross(a-c, b-c);
}
double getd2(point a, point b) {	//	两点距离
	return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y);
}

int andrew(point *P, int n, point *S) {	 //	P为点集合, A为凸包点
	sort(P, P+n);
	int tp = 0;
	for(int i=0; i<n; i++) {	//	下凸包
		while(tp>1 && dcmp(cross(S[tp-1]-S[tp-2], P[i]-S[tp-2]))<=0) tp--;
		S[tp++] = P[i];
	}
	for(int i=n-2, k=tp; ~i; i--) {	//	上凸包
		while(tp>k && dcmp(cross(S[tp-1]-S[tp-2], P[i]-S[tp-2]))<=0) tp--;
		S[tp++] = P[i];
	}
	return n > 1 ? tp - 1 : tp;
}

int rotating_calipers(int tp) {
	int q = 1;
	double ret = 0;
//	pa[++tp] = pa[0];
	for(int i=0; i<tp; i++) {
		while(xmult(pa[i], pa[i+1], pa[(q+1)%tp]) > xmult(pa[i], pa[i+1], pa[q]))
			q = (q + 1) % tp;	
		ret = max(ret, getd2(pa[i], pa[q]));
//		ret = max(ret, max(getd2(pa[i], pa[q]), getd2(pa[i+1], pa[q])));
	}
	return ret;
}

int main() {
	scanf("%d", &n);
	for(int i=0; i<n; i++) scanf("%lf%lf", &a[i].x, &a[i].y);
	int tp = andrew(a, n, pa);

	printf("%d\n", rotating_calipers(tp));
}
发布了221 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Scar_Halo/article/details/102799887