因为凸壳上对踵点的单调性所以旋转卡壳线性绕一圈就可以啦啦啦~~~
先求凸包,然后旋转卡壳记录$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
", 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;
}
没什么可说的了╮(๑•́ ₃•̀๑)╭