题意:
从n个点里选4个点围成一个四边形,求四边形的最大面积。
$n\leq 2000$。
题解:
枚举对角线,预处理每条对角线左边/右边的面积最大点,类似于旋转卡壳。
复杂度$O(n^{2})$。
代码:
#include<bits/stdc++.h> #define maxn 5005 #define maxm 500005 #define inf 0x7fffffff #define eps 1e-8 #define ll long long #define ld long double #define rint register int #define debug(x) cerr<<#x<<": "<<x<<endl #define fgx cerr<<"--------------"<<endl #define dgx cerr<<"=============="<<endl using namespace std; struct node{ ld x,y; node operator+(const node b)const{return (node){x+b.x,y+b.y};} node operator-(const node b)const{return (node){x-b.x,y-b.y};} ld operator*(const node b)const{return x*b.y-y*b.x;} //bool operator<(const node b)const{return x*b.y-y*b.x>0;} }A[maxn],S[maxn]; ld P[maxn][maxn]; inline int read(){ int x=0,f=1; char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘; return x*f; } inline ld dis(node a){return sqrt(a.x*a.x+a.y*a.y);} inline bool cmp1(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;} inline bool cmp2(node a,node b){return a*b>0 || (a*b==0 && dis(a)<dis(b));} inline int Graham(int n){ sort(A+1,A+1+n,cmp1); for(int i=n;i>=1;i--) A[i]=A[i]-A[1]; sort(A+2,A+1+n,cmp2); int top=0; for(int i=1;i<=n;S[++top]=A[i++]) while(top>=2 && (A[i]-S[top])*(S[top]-S[top-1])>=0) top--; for(int i=1;i<=top;i++) A[i]=S[i]; return top; } int main(){ int n=read(); for(int i=1;i<=n;i++) scanf("%Lf%Lf",&A[i].x,&A[i].y); n=Graham(n); for(int i=1;i<=n;i++) A[i+n]=A[i]; for(int i=1,k=1;i<=n;k=++i) for(int j=i+2;j<=n;j++){ while(k<=i || (k<j && (A[k]-A[i])*(A[j]-A[i])<(A[k+1]-A[i])*(A[j]-A[i]))) k++; P[i][j]=(A[k]-A[i])*(A[j]-A[i]); } for(int i=1,k=1;i<=n;k=++i) for(int j=i+2;j<=n;j++){ while(k<=j || (k<i+n && (A[j]-A[i])*(A[k]-A[i])<(A[j]-A[i])*(A[k+1]-A[i]))) k++; P[j][i]=(A[j]-A[i])*(A[k]-A[i]); } ld ans=0; for(int i=1;i<=n;i++) for(int j=i+2;j<=n;j++) ans=max(ans,P[i][j]+P[j][i]); printf("%.3Lf\n",ans*0.5); return 0; }
原文:https://www.cnblogs.com/YSFAC/p/13185295.html