[SCOI2007] 最大土地面积

题意:

从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;
}
最大土地面积

猜你喜欢

转载自www.cnblogs.com/YSFAC/p/13185295.html