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 }

 

 

你可能感兴趣的:(2007)