【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\n",maxn/2.);
69 }

 

posted @ 2017-11-23 20:10  AlphaInf  阅读(281)  评论(0编辑  收藏  举报