鏈結**:
旋轉卡殼可以用於求凸包的直徑、寬度,兩個不相交凸包間的最大距離和最小距離等。雖然演算法的思想不難理解,但是實現起來真的很容易讓人「卡殼」。
拿凸包直徑(也就是凸包上最遠的兩點的距離)為例,原始的演算法是這樣子:
直接按照這個描述可以實現旋轉卡殼演算法,但是**肯定相當冗長。逆向思考,如果qa,qb是凸包上最遠兩點,必然可以分別過qa,qb畫出一對平行線。通過旋轉這對平行線,我們可以讓它和凸包上的一條邊重合,如圖中藍色直線,可以注意到,qa是凸包上離p和qb所在直線最遠的點。於是我們的思路就是列舉凸包上的所有邊,對每一條邊找出凸包上離該邊最遠的頂點,計算這個頂點到該邊兩個端點的距離,並記錄最大的值。直觀上這是乙個o(n2)的演算法,和直接列舉任意兩個頂點一樣了。但是注意到當我們逆時針列舉邊的時候,最遠點的變化也是逆時針的,這樣就可以不用從頭計算最遠點,而可以緊接著上一次的最遠點繼續計算。於是我們得到了o(n)的演算法。
//計算凸包直徑,輸入凸包ch
,頂點個數為n,按逆時針排列,輸出直徑的平方
introtating_calipers(point *ch,
intn)
return
ans;
}很難想象這個看起來那麼麻煩的演算法只有這麼幾行**吧!其中cross函式是計算叉積,可以想成是計算三角形面積,因為凸包上距離一條邊最遠的點和這條邊的兩個端點構成的三角形面積是最大的。之所以既要更新(ch[p],ch[q])又要更新(ch[p+1],ch[q+1])是為了處理凸包上兩條邊平行的特殊情況。
#include #include #include #include using namespace std;
#define n 200005
struct point
len = top; res[++top] = pnt[n - 2];
for (i = n - 3; i >= 0; i--)
return top; // 返回凸包中點的個數
}__int64 rotating_calipers(point p,int n)
return ans;
}int main()
{ int i,n;
scanf("%d",&n);
for(i=0;i
凸包問題 旋轉卡殼
1978年,m.i.shamos在 computational ceometry 中介紹了一種尋找凸多邊形直徑的線性演算法。1.支撐線 如果一條直線l,通過凸多邊形p的乙個頂點,且多邊形在這條直線的一側,稱l是p的支撐線。2.對踵 zhong,三聲 點 如果過凸包上的兩個點可以畫一對平行直線,使凸包...
模板 凸包 旋轉卡殼
模板 凸包 旋轉卡殼 lrj 訓練指南 p272 對於個點按照 x 從小到大排序,再按照 y 點從小到大排序,刪除重複的點後,得到序列 p0,p1,p2.把 p0 和 p1 放入凸包。從p2開始,當新點在凸包 前進 方向的左邊時繼續,否則依次刪除最近加入凸包的點,直到新點在左邊 ps 判斷用叉積即可...
旋轉卡殼 凸包的直徑
poj 2187 直接求直徑ok 多邊形的直徑被定義為多邊形上任意兩點間的最大距離的值。在多邊形上,決定直徑的點可能不止一對。事實上,如果乙個多邊形含有n個頂點,那麼就最多有 n 對 直徑點對 在。上圖所示的是乙個簡單的多邊形直徑的例項。直徑點對在圖中是被平行的切線 用紅色表示 穿過的黑點.直徑是用...