您的位置:首页 > 其它

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

2016-06-12 22:39 288 查看
【题目链接】

显然四个点都在凸包上,按逆时针设为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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: