1. 程式人生 > >Luogu-4166 [SCOI2007]最大土地面積

Luogu-4166 [SCOI2007]最大土地面積

求平面內四邊形的最大面積

顯然四個端點都應該在凸包上,就先求凸包,然後\(n^2\)列舉四邊形對角線,對於一個點\(i\),順序列舉\(j\),同時用旋轉卡殼的方法去找離對角線最遠的兩個點。總時間複雜度\(n^2\)

luogu一遍過,但不知道為什麼BZOJ死活TLE...

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e4+100;
const double eps=1e-9;
struct Vector{
    double x,y;
    Vector(double a=0,double b=0){
        x=a,y=b;
    }
};
struct Point{
    double x,y;
    Point(double a=0,double b=0){
        x=a,y=b;
    }
}a[maxn],tmp[maxn];
int dcmp(double x){return fabs(x)<eps?0:x>0;}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
bool operator < (Point a,Point b){return a.x==b.x?a.y<b.y:a.x<b.x;}
bool operator == (Point a,Point b){return a.x==b.x&&a.y==b.y;}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double len(Vector x){return sqrt(dot(x,x));}
int n,m;
void tb(Point *p,int &n){
    if(n==1) return; 
    sort(p+1,p+n+1);
    tmp[m=1]=p[1];
    for(int i=2;i<=n;i++){
        while(m>1&&dcmp((tmp[m]-tmp[m-1])*(p[i]-tmp[m-1]))<=0)
            m--;
        tmp[++m]=p[i];
    }
    int k=m;
    for(int i=n-1;i>=1;i--){
        while(m>k&&dcmp((tmp[m]-tmp[m-1])*(p[i]-tmp[m-1]))<=0)
            m--;
        tmp[++m]=p[i];
    }
    n=m-1;
    for(int i=1;i<m;i++)
        p[i]=tmp[i];
}
double dists(Point p,Point a,Point b){
    Vector v1=b-a,v2=p-a;
    return fabs(v1*v2/len(v1));
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&a[i].x,&a[i].y);
    tb(a,n);
    double ans=0;
    a[n+1]=a[1]; 
    for(int i=1;i<=n;i++){
        int x=(i+2)%n+1,y=i%n+1;
        for(int j=i+2;j<=n;j++){
            while(x%n+1!=i&&dcmp(dists(a[x+1],a[i],a[j])-dists(a[x],a[i],a[j]))>0)
                x=x%n+1;
            while(y%n+1!=j&&dcmp(dists(a[y+1],a[i],a[j])-dists(a[y],a[i],a[j]))>0)
                y=y%n+1;
            double z=fabs((a[j]-a[i])*(a[x]-a[y]))/2;
            ans=max(ans,z);
        }
    }
    printf("%.3lf\n",ans);
    return 0;
}