【凸包模板】Graham算法、Andrew算法

参考:http://blog.csdn.net/bone_ace/article/details/46239187

这里我主要是学习Granham算法、Andrew算法,复杂度O(nlogn);

具体的算法过程可以参考上面的链接;


这里只提一个知识点:叉积


A x B 的值为正,则如上图所示,oab左旋,点b在向量oa左侧!


学习的过程就是把别人的模板变成自己的模板(不了解-->理解);

1.极角排序--Graham算法

const int maxn=1005;
int n,tot;
struct node
{
    double x,y;
} a[maxn],p[maxn];

double dis(node A,node B)              //距离
{
    return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
}

double x(node A,node B,node C)         //叉积公式
{
    return (B.x-A.x)*(C.y-A.y)-(C.x-A.x)*(B.y-A.y);
}

bool cmp(node A,node B)                //极角排序
{
    double pp=x(A,B,a[0]);
    if(pp>0) return true;
    if(pp<0) return false;
    return  dis(a[0],A)<dis(a[0],B);
}

void Graham()                          //Graham算法
{
    int k=0;
    for(int i=1; i<n; i++)
        if(a[i].y<a[k].y||(a[i].y==a[k].y&&a[i].x<a[k].x))
            k=i;
    swap(a[0],a[k]);
    sort(a+1,a+n,cmp);

    tot=2;
    p[0]=a[0],p[1]=a[1];
    for(int i=2; i<n; i++)
    {
        while(tot>0&&x(p[tot-2],p[tot-1],a[i])<=0) tot--;  //不带共线的!
        p[tot++]=a[i];
    }
}

2.水平排序--Andrew算法

int n,tot;
struct point
{
    double x,y;
};
point a[1005],p[1005];

double dis(point A,point B)                   //距离
{
    return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
}

double xmul(point A,point B,point C)         //叉积
{
    return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}

int cmp(point A,point B)                     //水平排序
{
    return (A.x<B.x||(A.x==B.x&&A.y<B.y));
}

void Andrew()                                //Andrew 算法
{
    sort(a,a+n,cmp);
    tot=0;
    for(int i=0;i<n;i++)
    {
        while(tot>1&&xmul(p[tot-2],p[tot-1],a[i])<0) tot--; //加共线的点!
        p[tot++]=a[i];
    }
    int k=tot;
    for(int i=n-2;i>=0;i--)
    {
        while(tot>k&&xmul(p[tot-2],p[tot-1],a[i])<0) tot--;
        p[tot++]=a[i];
    }
    if(n>1) tot--;
}

//如果是判断稳定凸包的话,使用水平排序;否则用极角排序;

//计算面积:double area(node p1,node p2,node p3)  return { ( (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y) ) / 2.0 ; } 叉积的一半;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值