BZOJ 1069 [SCOI2007]最大土地面积 旋转卡壳

题解:
现在写起旋转卡壳一气呵成~

枚举凸包上每个点i,然后顺时针逐个扫描整个凸包上的点p1,在此同时维护两个指针p2,p3,分别表示在i和p1连线两侧的离这条线最远的点,发现p2,p3是单调的~

总时间复杂度n^2的~

 

View Code
  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 
  8 #define N 2222
  9 #define EPS 1e-7
 10 
 11 using namespace std;
 12 
 13 struct PO
 14 {
 15     double x,y;
 16     void prt() {printf("%lf      %lf\n",x,y);}
 17 }p[N],stk[N<<1],o;
 18 
 19 int n,top;
 20 double ans;
 21 
 22 inline PO operator -(PO a,PO b)
 23 {
 24     a.x-=b.x; a.y-=b.y;
 25     return a;
 26 }
 27 
 28 inline int dc(double x)
 29 {
 30     if(x>EPS) return 1;
 31     else if(x<-EPS) return -1;
 32     return 0;
 33 }
 34 
 35 inline bool cmp(const PO &a,const PO &b)
 36 {
 37     if(dc(a.x-b.x)==0) return a.y<b.y;
 38     return a.x<b.x;
 39 }
 40 
 41 inline double cross(PO a,PO b,PO c)
 42 {
 43     return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
 44 }
 45 
 46 inline double getangle(const PO &a,const PO &b,const PO &c,const PO &d)
 47 {
 48     return cross(o,b-a,d-c);
 49 }
 50 
 51 inline void read()
 52 {
 53     scanf("%d",&n);
 54     for(int i=1;i<=n;i++)
 55         scanf("%lf%lf",&p[i].x,&p[i].y);
 56 }
 57 
 58 inline void graham()
 59 {
 60     sort(p+1,p+1+n,cmp);
 61     top=0;
 62     for(int i=1;i<=n;i++)
 63     {
 64         while(top>=2&&dc(cross(stk[top-1],stk[top],p[i]))<=0) top--;
 65         stk[++top]=p[i];
 66     }
 67     int tmp=top;
 68     for(int i=n-1;i>=1;i--)
 69     {
 70         while(top>=tmp+1&&dc(cross(stk[top-1],stk[top],p[i]))<=0) top--;
 71         stk[++top]=p[i];
 72     }
 73 }
 74 
 75 inline void rotating_calipers()
 76 {
 77     for(int i=1;i<top;i++) stk[top+i-1]=stk[i];
 78     for(int i=1;i<top;i++)
 79     {
 80         int p1=i+1;
 81         int p2=p1+1;
 82         int p3=p2+1;
 83         for(;p2<i+top-1;p2++)
 84         {
 85             while(1)
 86             {
 87                 double k=getangle(stk[i],stk[p2],stk[p1],stk[p1+1]);
 88                 if(dc(k)>=0) break;
 89                 else p1++;
 90             }
 91             while(1)
 92             {
 93                 double k=getangle(stk[p2],stk[i],stk[p3],stk[p3+1]);
 94                 if(dc(k)>=0) break;
 95                 else p3++;
 96                 if(p3-i>=top-1) break;
 97             }
 98             if(p3-i>=top-1) break;
 99             ans=max(ans,(fabs(cross(stk[i],stk[p1],stk[p2]))+fabs(cross(stk[i],stk[p2],stk[p3])))/2);
100         }
101     }
102 }
103 
104 inline void go()
105 {
106     graham();
107     rotating_calipers();
108     printf("%.3lf\n",ans);
109 }
110 
111 int main()
112 {
113     read(),go();
114     return 0;
115 }

 

 

posted @ 2013-03-05 21:39  proverbs  阅读(1559)  评论(3编辑  收藏  举报