BZOJ 1069: [SCOI2007]最大土地面积

最大面积一定出现在凸包上
先求出凸包,再枚举对角线,剩下的两个点用旋转卡壳得到

#include <bits/stdc++.h>

#define db double
#define pb push_back

const db eps = 1e-10;
inline int sign(db k) { return k < -eps ? -1 : k > eps; }
inline int cmp(db k1, db k2) { return sign(k1 - k2); }

struct P {
	db x, y;
	P() {}
	P(db x, db y): x(x), y(y) {}
	P operator + (const P &p) const { return {x + p.x, y + p.y}; }
	P operator - (const P &p) const { return {x - p.x, y - p.y}; }
	P operator * (db k) const { return {x * k, y * k}; }
	P operator / (db k) const { return {x / k, y / k}; }
	bool operator < (const P &p) const { int c = cmp(x, p.x); return c ? c == -1 : cmp(y, p.y) == -1; }
	bool operator == (const P &p) const { return !cmp(x, p.x) && !cmp(y, p.y); }
	db distTo(const P &p) const { return (*this - p).abs(); }
	db alpha() { return atan2(y, x); }
	void read() { scanf("%lf%lf", &x, &y); }
	void print() { printf("%.10f %.10f\n", x, y); }
	db abs() { return sqrt(abs2()); }
	db abs2() { return x * x + y * y; }
	P rot(const db &k) { return P(x * cos(k) - y * sin(k), x * sin(k) + y * cos(k)); }
	P rot90() { return P(-y, x); }
	P unit() { return *this / abs(); }
	P normal() { return rot90() / abs(); }
	int quad() const { return sign(y) == 1 || (sign(y) == 0 && sign(x) >= 0); }
	P getdel() {if (sign(x) == -1 || (sign(x) == 0 && sign(y) == -1)) return (*this) * (-1); else return (*this);}
	db dot(const P &p) { return x * p.x + y * p.y; }
	db det(const P &p) { return x * p.y - y * p.x; }
};

inline db cross(P p1, P p2, P p3) { return ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y)); }
inline int crossOp(P p1, P p2, P p3) { return sign(cross(p1, p2, p3)); }
inline db cross(P p1, P p2) { return p1.x * p2.y - p1.y * p2.x; }

// 凸包
std::vector<P> convexHull(std::vector<P> ps) {
	int n = ps.size(); if (n <= 1) return ps;
	std::sort(ps.begin(), ps.end());
	std::vector<P> qs(n * 2); int k = 0;
	for (int i = 0; i < n; qs[k++] = ps[i++])
		while (k > 1 && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k; i >= 0; qs[k++] = ps[i--])
		while (k > t && crossOp(qs[k - 2], qs[k - 1], ps[i]) <= 0) --k;
	qs.resize(k - 1);
	return qs;
}
inline db area(std::vector<P> ps) {
  db ans = 0;
  for (int i = 0, n = ps.size(); i < n; i++)
    ans += ps[i].det(ps[(i + 1) % n]);
  return std::fabs(ans / 2);
}

int main() {
	int n;
	scanf("%d", &n);
	std::vector<P> ps(n);
	for (int i = 0; i < n; i++)
		ps[i].read();
	std::vector<P> qs = convexHull(ps);	
	if (qs.size() == 4) {
		printf("%.3f\n", area(qs));
		return 0;
	}
	assert(qs.size() > 4);
	n = qs.size();
	qs.resize(n + 3);
	db ans = 0;
	for (int i = 0; i < n; i++) {
		int p1 = (i + 1) % n, p2 = (i + 2) % n;
		for (int j = i + 2; j < n; j++) {
			while (cmp(cross(qs[(p1 + 1) % n], qs[j], qs[i]), cross(qs[p1], qs[j], qs[i])) > 0)
				p1 = (p1 + 1) % n;
			while (cmp(cross(qs[i], qs[j], qs[(p2 + 1) % n]), cross(qs[i], qs[j], qs[p2])) > 0)
				p2 = (p2 + 1) % n;
			ans = std::max(ans, (cross(qs[p1], qs[j], qs[i]) + cross(qs[i], qs[j], qs[p2])) / 2.0);
		}
	}
	printf("%.3f\n", ans);
	return 0;
}
posted @ 2020-02-19 13:38  Mrzdtz220  阅读(93)  评论(0)    收藏  举报