zoukankan      html  css  js  c++  java
  • 【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 }
  • 相关阅读:
    MOSS中的User的Title, LoginName, DisplayName, SID之间的关系
    如何在Network Monitor中高亮间隔时间过长的帧?
    SharePoint服务器如果需要安装杀毒软件, 需要注意什么?
    如何查看SQL Profiler? 如何查看SQL死锁?
    什么是Telnet
    The name or security ID (SID) of the domain specified is inconsistent with the trust information for that domain.
    Windows SharePoint Service 3.0的某个Web Application无搜索结果
    网络连接不上, 有TCP错误, 如果操作系统是Windows Server 2003, 请尝试一下这里
    在WinDBG中查看内存的命令
    The virtual machine could not be started because the hypervisor is not running
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/7886757.html
Copyright © 2011-2022 走看看