首先,什麼是凸包?
假設平面上有p0~p12共13個點,過某些點作乙個多邊形,使這個多邊形能把所有點都「包」起來。當這個多邊形是凸多邊形的時候,我們就叫它「凸包」。如下圖:
這裡寫描述
然後,什麼是凸包問題?
我們把這些點放在二維座標系裡面,那麼每個點都能用 (x,y) 來表示。
現給出點的數目13,和各個點的座標。求構成凸包的點?
時間複雜度:o(n³)。
思路:兩點確定一條直線,如果剩餘的其它點都在這條直線的同一側,則這兩個點是凸包上的點,否則就不是。
步驟:
將點集裡面的所有點兩兩配對,組成 n(n-1)/2 條直線。
對於每條直線,再檢查剩餘的 (n-2) 個點是否在直線的同一側。
如何判斷乙個點 p3 是在直線 p1p2 的左邊還是右邊呢?(座標:p1(x1,y1),p2(x2,y2),p3(x3,y3))
這裡寫描述
當上式結果為正時,p3在直線 p1p2 的左側;當結果為負時,p3在直線 p1p2 的右邊。
時間複雜度:o(n㏒n)。
思路:應用分治法思想,把乙個大問題分成幾個結構相同的子問題,把子問題再分成幾個更小的子問題……。然後我們就能用遞迴的方法,分別求這些子問題的解。最後把每個子問題的解「組裝」成原來大問題的解。
步驟:
把所有的點都放在二維座標系裡面。那麼橫座標最小和最大的兩個點 p1 和 pn 一定是凸包上的點(為什麼呢?用反證法很容易證明,這裡不詳講)。直線 p1pn 把點集分成了兩部分,即 x 軸上面和下面兩部分,分別叫做上包和下包。
對上包:求距離直線 p1pn 最遠的點,即下圖中的點 pmax 。
作直線 p1pmax 、pnpmax,把直線 p1pmax 左側的點當成是上包,把直線 pnpmax 右側的點也當成是上包。
重複步驟 2、3。
對下包也作類似操作。
這裡寫描述
然而怎麼求距離某直線最遠的點呢?我們還是用到解一中的公式:
這裡寫描述
設有乙個點 p3 和直線 p1p2 。(座標:p1(x1,y1),p2(x2,y2),p3(x3,y3))
對上式的結果取絕對值,絕對值越大,則距離直線越遠。
注意:在步驟一,如果橫座標最小的點不止乙個,那麼這幾個點都是凸包上的點,此時上包和下包的劃分就有點不同了,需要注意。
時間複雜度:o(nh)。(其中 n 是點的總個數,h 是凸包上的點的個數)
思路:
縱座標最小的那個點一定是凸包上的點,例如圖上的 p0。
從 p0 開始,按逆時針的方向,逐個找凸包上的點,每前進一步找到乙個點,所以叫作步進法。
怎麼找下乙個點呢?利用夾角。假設現在已經找到 了,要找下乙個點:剩下的點分別和 p2 組成向量,設這個向量與向量p1p2的夾角為 β 。當 β 最小時就是所要求的下乙個點了,此處為 p3 。
這裡寫描述
注意:
找第二個點 p1 時,因為已經找到的只有 p0 乙個點,所以向量只能和水平線作夾角 α,當 α 最小時求得第二個點。
時間複雜度:o(n㏒n)
思路:graham掃瞄的思想和jarris步進法類似,也是先找到凸包上的乙個點,然後從那個點開始按逆時針方向逐個找凸包上的點,但它不是利用夾角。
這裡寫描述
步驟:
把所有點放在二維座標系中,則縱座標最小的點一定是凸包上的點,如圖中的p0。
把所有點的座標平移一下,使 p0 作為原點,如上圖。
計算各個點相對於 p0 的幅角 α ,按從小到大的順序對各個點排序。當 α 相同時,距離 p0 比較近的排在前面。例如上圖得到的結果為 p1,p2,p3,p4,p5,p6,p7,p8。我們由幾何知識可以知道,結果中第乙個點 p1 和最後乙個點 p8 一定是凸包上的點。
(以上是準備步驟,以下開始求凸包)
以上,我們已經知道了凸包上的第乙個點 p0 和第二個點 p1,我們把它們放在棧裡面。現在從步驟3求得的那個結果裡,把 p1 後面的那個點拿出來做當前點,即 p2 。接下來開始找第三個點:
連線p0和棧頂的那個點,得到直線 l 。看當前點是在直線 l 的右邊還是左邊。如果在直線的右邊就執行步驟5;如果在直線上,或者在直線的左邊就執行步驟6。
如果在右邊,則棧頂的那個元素不是凸包上的點,把棧頂元素出棧。執行步驟4。
當前點是凸包上的點,把它壓入棧,執行步驟7。
檢查當前的點 p2 是不是步驟3那個結果的最後乙個元素。是最後乙個元素的話就結束。如果不是的話就把 p2 後面那個點做當前點,返回步驟4。
這裡寫描述
說真的,這個演算法我也還沒有看清。網上的資料也少的可憐,我暫且把網上的解釋截個圖在這裡,往後搞懂以後再回來補上。
或者有人看懂了的,希望不吝指教,不甚感激!
擴充套件:以上討論的只是二維的凸包,如果延生為三維、多維的凸包問題呢?如何求解?
不過首先,二維凸包可以用來解決圍欄問題、城市規劃問題、聚類分析等等。但是三維、多維的凸包可能的使用範疇有哪些?
附:快包演算法**(c語言):
#include
凸包 Graham Scan演算法
graham scan演算法是一種靈活的凸包演算法,時間複雜度是o nlogn 演算法細節 1.選出最左下角的點 排序 x最小,其次是y最小 2.其餘點按極角排序,在極角相等的情況下距離極點 p 0 最近的優先 3.用乙個棧 陣列 儲存凸包上的點,先把p 0 p 1 壓入棧。4.掃瞄每乙個點,用叉積...
凸包 Andrew演算法
凸包的定義如下 在乙個點集d中,按一定順序選取子集q 使得q中所有點順次連線所構成的封閉凸多邊形包住d中所有點 可以形象地理解為 有許多個釘子釘在平面上,用一根牛皮筋把所有點包住 如下圖 andrew演算法是graham演算法的變種。其主要思想為把凸包上的點依次放入棧中,如果發現形成了凹多邊形 叉積...
Graham Scan凸包演算法
一 什麼是凸包 在乙個二維座標系中,有若干點雜亂排列著,將最外層的點連線起來構成的凸多邊型,它能包含給定的所有的點,這個多邊形就是凸包。尋找凸包的演算法有很多種,graham scan 演算法是一種十分簡單高效的二維凸包演算法,能夠在 o nlogn 的時間內找到凸包。二 graham scan 演...