zoukankan      html  css  js  c++  java
  • 【BZOJ 1069】 凸包+旋转卡壳

    1069: [SCOI2007]最大土地面积

    Description

      在某块平面土地上有N个点,你可以选择其中的任意四个点,将这片土地围起来,当然,你希望这四个点围成
    的多边形面积最大。

    Input

      第1行一个正整数N,接下来N行,每行2个数x,y,表示该点的横坐标和纵坐标。

    Output

      最大的多边形面积,答案精确到小数点后3位。

    Sample Input

    5
    0 0
    1 0
    1 1
    0 1
    0.5 0.5

    Sample Output

    1.000

    HINT

    数据范围 n<=2000, |x|,|y|<=100000

    【分析】

      这个叫旋转 qia 壳?

      好吧,去偷个gif回来。。

      

      其实还是形象生动,旋转卡壳是算点到线段的距离的,就是两条线扫啊扫,有点单调的意思。

      这题里,枚举四边形的对角线,然后两边找离这条线段的最远的点,可以证明这些点都是在凸包上的(好像很明显??)

      就直接在凸包上找,假设已经枚举了线段x-y,现在枚举x-y+1,卡壳线不断逆时针旋转就可以了(我的打法是逆时针旋转),因为前面去掉的点以后肯定也没有用的,嗯。。

      然后,这里要用到平面差积,差积的值是有正负的,所以用差积算面积的时候要小心一点。然后也是用差积比较斜率的。。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<iostream>
     6 using namespace std;
     7 #define Maxn 2010
     8 
     9 int n;
    10 
    11 const double eps=0.000001;
    12 struct P{double x,y;}a[Maxn],c[Maxn];
    13 int len;
    14 
    15 double mymax(double x,double y) {return x>y?x:y;}
    16 double myabs(double x) {return x<0?-x:x;}
    17 
    18 P operator - (P x,P y)
    19 {
    20     P tt;
    21     tt.x=x.x-y.x;tt.y=x.y-y.y;
    22     return tt;
    23 }
    24 
    25 int dcmp(double x)
    26 {  
    27     if(myabs(x)<eps) return 0;
    28    else return x<0?-1:1;
    29 }
    30 bool cmp(P x,P y) {return dcmp(x.x-y.x)==0?(x.y<y.y):(x.x<y.x);}
    31 double Dot(P x,P y) {return x.x*y.x+x.y*y.y;}
    32 double Cross(P x,P y) {return x.x*y.y-x.y*y.x;}
    33 
    34 void chull()
    35 {
    36     sort(a+1,a+1+n,cmp);
    37     len=0;    
    38     for(int i=1;i<=n;i++)
    39     {
    40         while(len>1&&Cross(c[len]-c[len-1],a[i]-c[len])<=0) len--;
    41         c[++len]=a[i];
    42     }
    43     int k=len;
    44     for(int i=n-1;i>=1;i--)
    45     {
    46         while(len>k&&Cross(c[len]-c[len-1],a[i]-c[len])<=0) len--;
    47         c[++len]=a[i];
    48     }
    49     len--;
    50 }
    51 
    52 double ans=0;
    53 void RC()//rotating calipers
    54 {
    55     for(int i=1;i<=len;i++)
    56     {
    57         int k1=i%len+1,k2=(i+2)%len+1;//两边一起做旋转卡壳
    58         for(int j=i+2;j<=len;j++)
    59         {
    60             while(k1%len+1!=j&&Cross(c[k1+1]-c[i],c[j]-c[i])>Cross(c[k1]-c[i],c[j]-c[i])) 
    61                 k1=k1%len+1;
    62             while(k2%len+1!=i&&Cross(c[j]-c[i],c[k2+1]-c[i])>Cross(c[j]-c[i],c[k2]-c[i]))
    63                 k2=k2%len+1;
    64             ans=mymax(ans,Cross(c[j]-c[i],c[k2]-c[i])+Cross(c[k1]-c[i],c[j]-c[i]));
    65         }
    66     }
    67 }
    68 
    69 
    70 int main()
    71 {
    72     scanf("%d",&n);
    73     for(int i=1;i<=n;i++)
    74     {
    75         scanf("%lf%lf",&a[i].x,&a[i].y);
    76     }
    77     chull();
    78     RC();
    79     printf("%.3lf
    ",ans/2);
    80     return 0;
    81 }
    View Code

    2016-12-10 09:44:52


    有一篇很好的讲旋转卡壳的博:

    http://blog.csdn.net/hanchengxi/article/details/8639476

  • 相关阅读:
    ylbtech-dbs-m-QQ邮箱
    ylbtech-Bill(发票管理)-数据库设计
    ylbtech-Recode(记录)-数据库设计
    ylbtech-LanguageSamples-Yield
    ylbtech-LanguageSamples-XMLdoc
    ylbtech-LanguageSamples-Versioning(版本控制)
    线程局部变量的使用
    守护线程的创建和运行
    有助于改善性能的技巧
    使用NIO提升性能
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6154909.html
Copyright © 2011-2022 走看看