【BZOJ1069】[SCOI2007]最大土地面積【凸包】

【題目鏈接】

顯然四個點都在凸包上,按逆時針設爲i, a, j, b,枚舉i和j,a和b都是單調的,複雜度爲O(n^2)


閒得無聊寫了個暴力。。

/* Forgive me Not */
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long double LD;
typedef double DB;

const int maxn = 100005;

int n, m;

struct Vector {
	DB x, y;

	Vector(DB a = 0, DB b = 0) {
		x = a; y = b;
	}

	bool operator < (const Vector &a) const {
		return x != a.x ? x < a.x : y < a.y;
	}

	Vector operator - (const Vector &a) {
		return Vector(x - a.x, y - a.y);
	}
} p[maxn], cov[maxn];

inline LD cross(Vector a, Vector b) {
	return a.x * b.y - a.y * b.x;
}

inline void Andrew() {
	sort(p + 1, p + 1 + n);
	for(int i = 1, k = 1; i <= n; i++) {
		for(; m > k && cross(cov[m] - cov[m - 1], p[i] - cov[m - 1]) <= 0; m--);
		cov[++m] = p[i];
	}
	for(int i = n - 1, k = m; i; i--) {
		for(; m > k && cross(cov[m] - cov[m - 1], p[i] - cov[m - 1]) <= 0; m--);
		cov[++m] = p[i];
	}
	if(n > 1) m--;
}

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);

	Andrew();

	LD ans = 0;
	if(m <= 80) {
		for(int i = 1; i <= m; i++) for(int j = i + 1; j <= m; j++) for(int k = j + 1; k <= m; k++) {
			LD tmp = cross(cov[j] - cov[i], cov[k] - cov[i]);
			for(int o = k + 1; o <= m; o++) ans = max(ans, tmp + cross(cov[k] - cov[i], cov[o] - cov[i]));
		}
	} else {
		for(int i = 1, a, b; i <= m; i++) {
			a = i + 1; b = i + 3;
			if(a > m) a -= m;
			if(b > m) b -= m;
			for(int j = i + 2; j <= m; j++) {
				for(; a != j && cross(cov[a + 1] - cov[i], cov[j] - cov[i]) > cross(cov[a] - cov[i], cov[j] - cov[i]); a == m ? a = 1 : a++);
				for(; b != i && cross(cov[j] - cov[i], cov[b + 1] - cov[i]) > cross(cov[j] - cov[i], cov[b] - cov[i]); b == m ? b = 1 : b++);
				ans = max(ans, cross(cov[a] - cov[i], cov[j] - cov[i]) + cross(cov[j] - cov[i], cov[b] - cov[i]));
			}
		}
	}

	printf("%.3f", (DB)ans / 2);
	return 0;
}


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