• 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 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    【PyMuPDF和pdf2image】Python将PDF转成图片PNG和JPG
    How to extract images from PDF in Python? 通过python从pdf文件中提取图片
    linux shell 用sed命令在文本的行尾或行首添加字符
    shell中的if语句
    Linux find 用法示例
    Linux 自动删除N小时或分钟前的文件
    记一次Linux磁盘空间占满无法删除的故障
    Shell字符串拼接(连接、合并)
    shell脚本使用之awk按列求平均值(含最大,最小值)
    LVM实现将2块磁盘总空间“合二为一”并挂载到同一目录
  • 原文地址:https://www.cnblogs.com/proverbs/p/2945121.html
Copyright © 2020-2023  润新知