Graham's Scan求凸包(convex hull)

graham's scan 求凸包:

先将所有点根据x,y按字典序排序,显然字典序最小的和最大的都是凸包上的点,字典序最小的是凸包中左下角的点,字典序最大的是凸包上右上角的点。(设字典序最小的点为A,如下图第0个点,字典序最大的点为B,如下图第6个点)

那么整个凸包就被A、B分成了两条链,A->B,B->A。那么就只要分别从A和B开始不断增加点得到这两条链就可以了。由于graham's scan是逆时针求凸包的,而凸包上的点所连出的线段的斜率在逆时针方向都是不断变大的,所以在求上下链的时候,如果新增加的这个点使斜率减小那么就会出现凹进去的情况,那么舍掉这个点就可以了。

 

模板题:Beauty Contest

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;

struct P
{
    int x,y;
    bool operator <(P t)const
    {
        if(x==t.x)return y<t.y;
        else return x<t.x;
    }
    P operator -(P t)
    {
        return (P){x-t.x,y-t.y};
    }
    int det(P t)//用来判断两条线段的斜率是递增还是递减
    {
        return x*t.y-y*t.x;
    }
    int dot(P t)
    {
        return x*t.x+y*t.y;
    }
};

const int M=5e4+20;
int k,n;
P s[M],c[M];

void get_c()//求凸包
{
    k=0;
    sort(s,s+n);
    for(int i=0;i<n;i++)//增加新点,求下面的链,A->B
    {
        while(k>1&&(c[k-1]-c[k-2]).det(s[i]-c[k-1])<=0)k--;//保证所有线段的斜率是递增的
        c[k++]=s[i];
    }
    for(int i=n-2,t=k;i>=0;i--)//求上面的链,B->A
    {
        while(k>t&&(c[k-1]-c[k-2]).det(s[i]-c[k-1])<=0)k--;
        c[k++]=s[i];
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&s[i].x,&s[i].y);
    }
    get_c();
    int ans=0;
    for(int i=0;i<k;i++)
    {
        for(int j=0;j<k;j++)
            if(i!=j)
            ans=max(ans,(c[i]-c[j]).dot(c[i]-c[j]));
    }
    printf("%d\n",ans);
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值