凸包算法

                凸包

     今天看了一下凸包,自己理解的也不是很深,在這裏說說自己的理解 


   凸包:在二維歐幾里得空間中,凸包可想象爲一條剛好包著所有點的橡皮圈。
      用不嚴謹的話來講,給定二維平面上的點集,凸包就是將最外層的點連接起來構成的凸多邊型,它能          包含點集中所有的點。--百度百科

      
      這幾個用藍線連起來的紅點就組成了一個凸包
                         
      
      

     如何求這個凸包呢


                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];
    }
}
如有錯誤,望指出^_^


 
        


發佈了74 篇原創文章 · 獲贊 48 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章