• 【BZOJ1069】【SCOI2007】最大土地面积


    题目大意:给定有n个点的点集,求该点集中任意四个点所构成的四边形中面积最大四边形的面积。

    我们不难想到(不难yy出来),面积最大的四边形的四个顶点一定所给定的点集所构成的凸包上。我们求出给定点集的集合后,枚举一条对角线,由该对角线将凸包分为上下两部分,分别求出两个面积最大的三角形,面积加起来然后更新即可。对于每一次枚举,对角线的长度是固定的,由于凸包具有某些特殊性性质,我们可以通过三分求出面积最大的三角形的顶点,然后就OK了。

    时间复杂度:$O(n^{2}*log(n))$。

    刚开始因为我写得太挫,导致被卡了常数(1.1s),后来将原先两点距离公式+海伦公式求三角形面积法改为了铅锤法,从1100+ms降低至450ms才AC。

    PS:此题其实可以用二分,三分有点多余(但是我不想改了啦啦啦)。

     1 #include<bits/stdc++.h>
     2 #define M 100000
     3 #define y0 y123
     4 #define pi acos(-1)
     5 using namespace std;
     6 double x0,y0=1e20;
     7 struct node{
     8     double x,y; node(){x=y=0;}
     9     node(double xx,double yy){x=xx; y=yy;}
    10     friend bool operator <(node a,node b){
    11         double ap1=atan((a.y)/(a.x));
    12         double ap2=atan((b.y)/(b.x));
    13         if(ap1<0) ap1=pi+ap1;
    14         if(ap2<0) ap2=pi+ap2;
    15         return ap1<ap2;
    16     }
    17     friend node operator -(node a,node b){return node(a.x-b.x,a.y-b.y);}
    18     friend double operator *(node a,node b){return a.x*b.y-a.y*b.x;}
    19 }a[M],s[M];
    20 double dis(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
    21 double gets(int i,int j,int k){
    22     node A=s[i],B=s[j],C=s[k];
    23     double d,K,b;
    24     if(A.x>B.x) swap(A,B);
    25     if(A.x>C.x) swap(A,C);
    26     if(B.x>C.x) swap(B,C);
    27     K=(A.y-C.y)/(A.x-C.x); b=A.y-A.x*K;
    28     d=K*B.x+b;
    29     return abs(d-B.y)*(C.x-A.x);
    30 }
    31  
    32 int main(){
    33     int n,use=0; scanf("%d",&n);
    34     for(int i=1;i<=n;i++){
    35         double x,y; cin>>x>>y;
    36         a[i]=node(x,y);
    37         if(y<a[1].y) swap(a[1],a[i]);
    38     }
    39     for(int i=2;i<=n;i++) a[i]=a[i]-a[1];
    40     a[1]=node(0,0);
    41     sort(a+2,a+n+1); a[n+1]=a[1];
    42     s[++use]=a[1]; s[++use]=a[2];
    43     for(int i=3;i<=n+1;i++){
    44         while(use>1&&(a[i]-s[use-1])*(s[use]-s[use-1])>0) use--;
    45         if(i<=n) s[++use]=a[i];
    46     }
    47     n=use; double maxn=0;
    48     for(int i=1;i<=n;i++) s[i+n]=s[i];
    49     for(int i=1;i<=n;i++)
    50     for(int j=i+1;j<=n;j++){
    51         double sup=0,sdn=0,now=0;
    52         int l=i,r=j;
    53         while(r-l>3){
    54             int mid1=(l+l+r)/3,mid2=(l+r+r)/3;
    55             if(gets(i,j,mid1)>gets(i,j,mid2)) r=mid2;
    56             else l=mid1;
    57         }
    58         for(int k=l;k<=r;k++) sup=max(sup,gets(i,j,k));
    59         l=j; r=n+i-1;
    60         while(r-l>3){
    61             int mid1=(l+l+r)/3,mid2=(l+r+r)/3;
    62             if(gets(i,j,mid1)>gets(i,j,mid2)) r=mid2;
    63             else l=mid1;
    64         }
    65         for(int k=l;k<=r;k++) sdn=max(sdn,gets(i,j,k));
    66         maxn=max(maxn,sup+sdn);
    67     }
    68     printf("%.3lf
    ",maxn/2.);
    69 }
  • 相关阅读:
    自学Linux Shell14.3-创建临时文件
    自学Linux Shell14.2-在脚本中使用其他文件描述符
    自学Linux Shell14.1-理解输入输出
    自学Linux Shell13.3-获得用户输入(read命令)
    自学Linux Shell13.2-选项处理(主要getopt、getopts命令)
    自学Linux Shell13.1-命令行参数
    自学Linux Shell12.8-循环实例
    自学Linux Shell12.7-控制循环break、continue命令
    自学Linux Shell12.6-嵌套循环for命令
    自学Linux Shell12.5-while、until命令
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7886757.html
Copyright © 2020-2023  润新知