凸包算法

                凸包

     今天看了一下凸包,自己理解的也不是很深,在这里说说自己的理解 


   凸包:在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
      用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能          包含点集中所有的点。--百度百科

      
      这几个用蓝线连起来的红点就组成了一个凸包
                         
      
      

     如何求这个凸包呢


                1.首先我们先对这些点进行极角排序
                            
                         极角排序:找y最小的点,如果y最小的点有好几个,那就找x最小的点,相同的点排除掉,把这个点做为                     基点H,接下来所有的点针对该点的射线,按角度由小到大,若相同按距离由近到远来排序
                 
                  如何判断角度的大小,需要左转判定,假如有两个点p1,p2,求出向量<p1,H> (x1,y1)和<p2,H> (x2,y2),
                  如果 x1*y2-x2*y1>0 说明p1到p2左转    
                 
                            排序后应该是这样
     
             

       2.排完序,我们就可以从基点开始找凸包了(Graham算法)
                         1.把排完序的点p0,p1,p2入栈
                         2.判断p[i]与栈内的stack[top],stack[top-1],p[i]到stack[top]是否左转了,如果是,出栈,直到找到
                            p[i]相对于栈内没有左转的时候,把p[i]进栈

                           过程大概是这样的

        第一步  0 , 1 ,2入栈            第二步   1到3左转,2出栈

          
         第三步  1到4右转,4入栈           最后遍历完成,凸包形成
            

         
                          3.遍历完后stack里存的凸包的点,top+1代表点的个数
                          
                           
下面是代码
struct node
{
    long long x,y;
}q[51234],stack1[51234];
int n,top;
long long dist(node p1,node p2) //两点距离的平方
{
    return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}
long long mult(node p1,node p2,node p0)  //判断是否左转
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
int cmp(node p1,node p2)   //极角排序的比较函数
{
    if(mult(p1,p2,q[0])>0)
        return 1;
    else if(mult(p1,p2,q[0])==0 && dist(p1,q[0])<dist(p2,q[0]))  //相等的按距离近的
        return 1;
    return 0;
}
void Gramham()
{
    int i,k=0;
    for(i=0;i<n;i++)
    {
        if(q[i].y<q[k].y || (q[i].y==q[k].y && q[i].x<q[k].x)) //找y最小的点,y相等找x最小的点
        k=i;
    }
    node tep;
    tep=q[0];
    q[0]=q[k];
    q[k]=tep;
    sort(q+1,q+n,cmp);
    stack1[0]=q[0];
    stack1[1]=q[1];
    stack1[2]=q[2];
    top=2;
    for(i=3;i<n;i++)
    {
        while(top>1 && mult(q[i],stack1[top],stack1[top-1])>=0)  //是否左转,是继续判断,不是,就入栈
            top--;
        stack1[++top]=q[i];
    }
}
如有错误,望指出^_^


 
        


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值