凸包的判定(模板)

第一次学习凸包的判定哈,开始一直想不通为什么要从小到大判一遍后又要从大到小再判一遍

然后自己画了个图,终于知道了

先上模板

数据结构:

struct Point {
    double x;
    double y;
    Point(double a = 0, double b = 0) : x(a), y(b) {}
    friend bool operator < (const Point &l, const Point &r) {//以y为第一优先级,x为第二优先级
        return l.y < r.y || (l.y == r.y && l.x < r.x);
    }
} p[MAXN], ch[MAXN * 2], tmp[MAXN];

判断凸包:

double mult(const Point &a, const Point &b, const Point &o) {
    return (a.x - o.x) * (b.y - o.y) >= (b.x - o.x) * (a.y - o.y);//b到o的斜率大于a到o的斜率
}

主函数:

int Graham(Point *p,int n,Point* Set)//p为点集(从1开始一共有n个)set为逆时针以最左下开始的构成凸包的点集,返回值是构成凸包的点的个数
{
    sort(p+1,p+n+1);
    int head;

    if (n<3) return 0;

    Set[1]=p[1];Set[2]=p[2];
    head=2;

    for (int k=3;k<=n;k++)
    {
        while(head!=1)
            if (mult(p[k],Set[head],Set[head-1])) head--;
            else break;
        Set[++head]=p[k];
    }

    int len=head;
    Set[++head]=p[n-1];

    for (int k=n-2;k>=1;k--)
    {
        while(head!=len)
            if (mult(p[k],Set[head],Set[head-1])) head--;
            else break;
        Set[++head]=p[k];
    }

    return --head;
}


为什么要判两遍呢,其实我们可以看看排序算法

我们的p[0]其实是左下的一个点,然后p[n-1]其实是右上的一个点

我们正着来一遍的话就只是逆时针从左下到右上点做了一个凸包,接下来还要从右上到左上做一个凸包,这才能算是完整的凸包

同时我们可以看到,我们起点入队了两次,所以咱们最后要return --head;



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值