首页 > 代码库 > NYOJ_253:LK的旅行(旋转卡壳入门)

NYOJ_253:LK的旅行(旋转卡壳入门)

题目链接

求平面最大点对。

找凸包 -> 根据凸包运用旋转卡壳算法求最大点对(套用kuang巨模板)

关于旋转卡壳算法

#include<bits/stdc++.h>
using namespace std;

struct point
{
    int x,y;
    point operator -(const point& rhs)const
    {
        point ret;
        ret.x=x-rhs.x;
        ret.y=y-rhs.y;
        return ret;
    }
    int operator *(const point& rhs)const//叉乘
    {
        return x*rhs.y-y*rhs.x;
    }
    bool operator <(const point& rhs)const
    {
        return x<rhs.x||x==rhs.x&&y<rhs.y;
    }
} p[100005],s[100005];
int top;

bool ok(point A,point B,point C)    //判断ABC是否是按逆时针顺序给出
{
    return (B-A)*(C-A)>0;
}
int dist2(point a,point b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
int rotating_calipers()
{
    int ret = 0;
    point v;
    int cur = 1;
    for(int i = 0; i < top; i++)
    {
        v = s[i]-s[(i+1)%top];
        while((v*(s[(cur+1)%top]-s[cur])) < 0)
            cur = (cur+1)%top;
        ret = max(ret,max(dist2(s[i],s[cur]),dist2(s[(i+1)%top],s[(cur+1)%top])));
    }
    return ret;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%d%d",&p[i].x,&p[i].y);

        sort(p,p+n);
        top=0;
        for(int i=0; i<n; i++)  //求下凸包
        {
            while(top>=2 && !ok(s[top-2],s[top-1],p[i]))
                top--;
            s[top++]=p[i];
        }
        int t=top-1;
        for(int i=n-1; i>=0; i--)  //求上凸包
        {
            while(top>=t+2 && !ok(s[top-2],s[top-1],p[i]))
                top--;
            s[top++]=p[i];
        }
        --top;    //    首尾点相同,故舍去
        int ans=rotating_calipers();
        printf("%d\n",ans);
    }
}

 

NYOJ_253:LK的旅行(旋转卡壳入门)