凸包問題 旋轉卡殼

2021-09-11 19:26:12 字數 1897 閱讀 5830

2023年,m.i.shamos在**《computational ceometry》中介紹了一種尋找凸多邊形直徑的線性演算法。

1.支撐線:如果一條直線l,通過凸多邊形p的乙個頂點,且多邊形在這條直線的一側,稱l是p的支撐線。

2.對踵(zhong,三聲)點:如果過凸包上的兩個點可以畫一對平行直線,使凸包上所有點都夾在兩條平行線之間||落在平行線上,那麼這兩個點稱為一對對踵點。兩條平行的支撐線所過的兩點就是一對對踵點。可以證明,乙個凸n邊形的對踵點最多只有3n/2(對上取整)對。

3.凸多邊形的直徑:將乙個凸多邊形上任意兩點間的距離的最大值定義為多邊形的直徑。確定這個直徑的點對數可能多於一對。事實上,對於擁有n個頂點的多邊形,就可能有n對「直徑點對」存在。

存在乙個凸多邊形直徑定理:凸多邊形p的直徑=p的所有平行支撐線之間距離的最大值,因此,凸多邊形的直徑可以在對踵點對之間尋找。

step1:計算多邊形y方向上的端點,稱之為ymin和ymax。

step2:通過ymin和ymax構造兩條水平切線,由於他們已經是一對對踵點,計算他們之間的距離並維護乙個當前最大值。

step3:同時旋轉兩條直線到其中一條與多邊形的一條邊重合。

step4:乙個新的對踵點對此時產生,計算新的距離,並和當前最大值進行比較,若大於當前最大值。則更新。

step5:重複step3和step4的過程直到再次產生新的對踵點對。

step6:輸出最大直徑的對踵點對。

可以看出,如果單對乙個凸包進行旋轉卡殼,其時間複雜度為o(n),然而,由於一般在此之前要計算凸包,其時間複雜度為o(nlogn),因此,求一組點的最大距離的時間複雜度一般為o(nlogn)。

當然,如果按照上面所說的實現的話,感覺好麻煩,於是我們可以換成三角形面積,然後乙個乙個的替換。可以產生一樣的效果。

例如:step2中每次查詢一對對踵點,我們就可以轉換成求三角形的面積:如圖,紅色和藍色三角形。最後比較的時候,比較最後的兩條線即可。

下面給出一**來形象的解釋演算法步驟:

第一次比較,即線段ab和三角形abc之間比面積,得到:符合,q=(q+1)%n;q=2;

第二次比較,即三角形abc和三角形acd之間比面積,得到:符合,q=(q+1)%n;q=3;

第三次比較,即三角形abd和三角形abe之間,進過我仔細的比較,發現abd比較大,因此結束while迴圈,ans更新為max(ad,be),再次經過我仔細的比較,發現be較長,因此ans更新為distance(d,e);

i++,繼續迴圈,直到遍歷完所有的頂點。

演算法的思路比較簡單,實現也不難,只用幾行**即可。

code:

struct point

friend point operator + (const point &a,const point &b)

friend point operator - (const point &a,const point &b)

friend double operator ^ (point a,point b)

};double dis(point a,point b)

double rotatecalipers(point *ch,int n){//傳入點集和集合元素個數

double ans=-inf32;int q=1;

ch[n]=ch[0];

for(int i=0;i然後是一些oj 的測試來驗證這個板子了:

accode:

模板 凸包 旋轉卡殼

模板 凸包 旋轉卡殼 lrj 訓練指南 p272 對於個點按照 x 從小到大排序,再按照 y 點從小到大排序,刪除重複的點後,得到序列 p0,p1,p2.把 p0 和 p1 放入凸包。從p2開始,當新點在凸包 前進 方向的左邊時繼續,否則依次刪除最近加入凸包的點,直到新點在左邊 ps 判斷用叉積即可...

旋轉卡殼 凸包的直徑

poj 2187 直接求直徑ok 多邊形的直徑被定義為多邊形上任意兩點間的最大距離的值。在多邊形上,決定直徑的點可能不止一對。事實上,如果乙個多邊形含有n個頂點,那麼就最多有 n 對 直徑點對 在。上圖所示的是乙個簡單的多邊形直徑的例項。直徑點對在圖中是被平行的切線 用紅色表示 穿過的黑點.直徑是用...

旋轉卡殼求凸包直徑

直徑即最長的兩點的距離 列舉凸包上的所有邊,對每一條邊找出凸包上離該邊最遠的頂點 用叉積 計算這個頂點到該邊兩個端點的距離,並記錄最大的值。但是注意到當我們逆時針列舉邊的時候,最遠點的變化也是逆時針的,這樣就可以不用從頭計算最遠點,而可以緊接著上一次的最遠點繼續計算。於是我們得到了o n 的演算法。...