BZOJ-1069 [SCOI2007]最大土地面积
先把位于凸包的点求出,然后n^2枚举每两个点x,y,接着左右边找个离线最远的点。
可以知道,当x不变y单调递增时,两边距离最远的两点也在单调递增。
于是可以使用旋转卡壳。
#include <cstdlib> #include <cstdio> #include <cstring> #include <cmath> #include <iostream> #include <algorithm> #include <cctype> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define maxn 2009 #define pi acos(-1) #define eps 1e-11 using namespace std; inline int read() { int x=0, f=1; char ch=getchar(); while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=x*10+ch-'0', ch=getchar(); return x*f; } struct P{double x, y;} p[maxn], s[maxn]; P operator - (P a, P b){return (P){a.x-b.x, a.y-b.y};} double operator * (P a, P b){return a.x*b.y-a.y*b.x;} double dis(P a, P b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);} bool cmp(P a, P b) { double t=(a-p[1])*(b-p[1]); if (t==0) return dis(a, p[1])<dis(b, p[1]); else return t<0; } int n, top; double ans; int main() { n=read(); rep(i, 1, n) scanf("%lf%lf", &p[i].x, &p[i].y); int k=1; rep(i, 2, n) if (p[i].y<p[k].y || (p[i].y==p[k].y && p[i].x<p[k].x)) k=i; swap(p[1], p[k]); sort(p+2, p+n+1, cmp); s[++top]=p[1]; s[++top]=p[2]; rep(i, 3, n) { while (top>1 && (p[i]-s[top-1])*(s[top]-s[top-1])<=0) top--; s[++top]=p[i]; } s[top+1]=p[1]; int a, b; rep(x, 1, top) { a=x%top+1; b=(x+2)%top+1; rep(y, x+2, top) { while (a%top+1!=y && (s[y]-s[x])*(s[a+1]-s[x])>(s[y]-s[x])*(s[a]-s[x])) a=a%top+1; while (b%top+1!=x && (s[b+1]-s[x])*(s[y]-s[x])>(s[b]-s[x])*(s[y]-s[x])) b=b%top+1; ans=max((s[y]-s[x])*(s[a]-s[x])+(s[b]-s[x])*(s[y]-s[x]), ans); } } printf("%.3lf\n", ans/2); return 0; }