POJ-2079/HDU 3934___Triangle —— 旋转卡壳 + 最大三角形面积

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

题目大意:

    求二维平面内能组成的最大三角形面积

解题思路:

    最大三角形肯定在凸包上
    假设三个点为 i p q i,p,q ,枚举 i i
    固定 i p i,p 后,旋转 q q ,易得凸包是个单峰函数
    所以在第一个下降的地方就是答案
    然后固定 i q i,q ,旋转 p p ,再求一遍答案
    此时即找到三角形一点为 i i 的最大面积
    时间复杂度: O ( n 2 ) O(n^2)

    为什么可以这样找?看了下别人的是继续枚举点 p p ,根据单调性使得 q q 点一定只能往前移动,那么我的为什么是对的?希望有大佬解答一下。

核心:旋转卡壳

#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);
}

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;
}

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

int main() {
    while(~scanf("%d", &n) && n!=-1){
		for(int i=0; i<n; i++) scanf("%lf%lf", &a[i].x, &a[i].y);
	    int tp = andrew(a, n, pa);
	    
		printf("%.2f\n", 0.5 * rotating_calipers(tp));	
	}
}
发布了221 篇原创文章 · 获赞 220 · 访问量 2万+

猜你喜欢

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