【BZOJ 1069】【SCOI 2007】最大土地面积 凸包+旋转卡壳
因为凸壳上对踵点的单调性所以旋转卡壳线性绕一圈就可以啦啦啦~~~
先求凸包,然后旋转卡壳记录$sum1$和$sum2$,最后统计答案就可以了
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define read(x) x=getint() #define N 2003 using namespace std; inline int dcmp(double x) {return fabs(x) < 1e-6 ? 0 : (x < 0 ? -1 : 1);} struct Point { double x, y; Point(double _x = 0, double _y = 0) : x(_x), y(_y) {} } a[N], tu[N]; Point operator - (Point a, Point b) { return Point(a.x - b.x, a.y - b.y); } inline double Cross(Point a, Point b) { return a.x * b.y - a.y * b.x; } inline double S(Point a, Point b, Point c) { return Cross(a - c, b - c); } int n, top = 0; double sum1[N][N], sum2[N][N]; inline bool cmp(Point X, Point Y) { return X.y == Y.y ? X.x < Y.x : X.y < Y.y; } inline void mktb() { for(int i = 1; i <= n; ++i) { while (top > 1 && dcmp(S(tu[top], a[i], tu[top-1])) != 1) --top; tu[++top] = a[i]; } int k = top; for(int i = n-1; i > 0; --i) { while (top > k && dcmp(S(tu[top], a[i], tu[top - 1])) != 1) --top; tu[++top] = a[i]; } tu[0] = tu[top - 1]; n = top - 1; } inline void mksum() { int nxt, j; for(int i = 0; i < n; ++i) { nxt = (i + 2) % n; for(int tmp = 1; tmp <= n - 2; ++tmp) { j = (i + tmp) % n; while (S(tu[j], tu[nxt], tu[i]) < S(tu[j], tu[(nxt + 1) % n], tu[i])) nxt = (nxt + 1) % n; sum1[i][j] = S(tu[j], tu[nxt], tu[i]); } nxt = (i - 2 + n) % n; for(int tmp = 1; tmp <= n - 2; ++tmp) { j = (i - tmp + n) % n; while (S(tu[nxt], tu[j], tu[i]) < S(tu[(nxt - 1 + n) % n], tu[j], tu[i])) nxt = (nxt - 1 + n) % n; sum2[i][j] = S(tu[nxt], tu[j], tu[i]); } } } inline void AC() { double ans = 0; for(int i = 0; i < n - 2; ++i) for(int j = i + 2; j < n; ++j) ans = max(ans, sum1[i][j] + sum2[i][j]); printf("%.3lf\n", ans / 2); } int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) scanf("%lf%lf", &a[i].x, &a[i].y); sort(a + 1, a + n + 1, cmp); mktb(); mksum(); AC(); return 0; }
没什么可说的了╮(๑•́ ₃•̀๑)╭
NOI 2017 Bless All