• 旋转卡壳(rotate吧)


    旋转卡壳,我是不会纠结ta到底念什么的,ta应该有2^4种读法
    ————-lrh

    旋转卡壳算法(Rotating Calipers Algorithm):
    是解决一些与凸包有关问题的有效算法 就像一对卡壳卡住凸包旋转而得名
    一半可以用来O(n)求凸包中两点的最远距离
    这里写图片描述
    被一对卡壳正好卡住的对应点对称为对踵点(Antipodal point)
    这里写图片描述
    这里写图片描述
    上第一个图是卡壳的一般情况:卡住两点
    图二是卡住一条边和一个点
    由于实现中,卡住两点的情况不好处理,我们通常关注第二种情况
    在第二种情况中,我们可以看到,一个对踵点和对应边之间的距离比其他点要大
    也就是一个对踵点和对应边所形成的三角形是最大的
    这里写图片描述
    可以注意到,A是凸包上离B所在直线最远的点
    于是我们的思路就是枚举凸包上的所有边,对每一条边找出凸包上离该边最远的顶点,
    计算这个顶点(不一定只计算一个顶点,具体看代码解释)到该边两个端点的距离,并记录最大的值
    直观上这是一个O(n^2)的算法,和直接枚举任意两个顶点一样了
    但是注意到当我们逆时针枚举边的时候,最远点的变化也是逆时针的,
    这样就可以不用从头计算最远点,
    而可以紧接着上一次的最远点继续计算
    于是我们得到了O(n)的算法

    看一下代码吧

    void KK()
    {
        sta[++top]=sta[1];
        int k=1,ans=0;   //k枚举的点编号 
        for (int i=1;i<top;i++)
        {
            while (fabs(Cross(po[sta[i+1]]-po[sta[i]],po[sta[k+1]]-po[sta[i]]))>
                  fabs(Cross(po[sta[i+1]]-po[sta[i]],po[sta[k]]-po[sta[i]])))
            {
                k++;
                if (k==top) k=1;    
            }
            ans=max(ans,max(ds(po[sta[k]],po[sta[i]]),ds(po[sta[k+1]],po[sta[i]])));
            ans=max(ans,max(ds(po[sta[k]],po[sta[i+1]]),ds(po[sta[k+1]],po[sta[i+1]])));
        }
        printf("%d",ans);
    }

    解释一下:

    这里写图片描述
    保证栈里的是一个环

    这里写图片描述
    环的操作,让点循环起来

    这里写图片描述
    while中的判断是把点到直线的距离变成三角形面积的判断
    每次我们找出来一对对踵点,就需要计算一下该点和这条边的两个端点的距离,取一个max,
    注意Cross是有正有负的,所以前面要加上一个fabs

    这里写图片描述
    统计答案,i和i+1要分别和k,k+1进行计算,
    为了防止k—>k+1和i—>i+1这两条边平行的情况

  • 相关阅读:
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    tctip demo页面>
    sql 随笔
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673429.html
Copyright © 2020-2023  润新知