最初接觸旋轉卡殼(應該讀xuán zhuǎn qiǎ ké)是在csu上的一道題(這道題至今沒a,也不知道是是嗎玄學操作,更新:ac了,輸出記得用%f),不過這不重要,重要是學到了新知識!
2023年, m.i. shamos』s ph.d. 的**」computational geometry」標誌著電腦科學的這一領域的誕生。 當時他發表成果的是乙個尋找凸多邊形直徑的乙個非常簡單的演算法, 即根據多邊形的一對點距離的最大值來確定。
後來直徑演化為由一對對踵點對來確定。 shamos提出了乙個簡單的 o(n) 時間的演算法來確定乙個凸 n 角形的對踵點對。 因為他們最多只有 3n/2 對, 直徑可以在 o(n) 時間內算出。
如同toussaint後來提出的, shamos的演算法就像繞著多邊形旋轉一對卡殼。 因此就有了術語「旋轉卡殼」。 2023年, toussaint發表了一篇**, 其中用同樣的技術來解決許多問題。 從此, 基於此模型的新演算法就確立了, 解決了許多問題。
他們包括:
計算距離
凸多邊形直徑
凸多邊形寬
凸多邊形間最大距離
凸多邊形間最小距離
外接矩形
最小面積外接矩形
最小周長外接矩形
三角剖分
洋蔥三角剖分
螺旋三角剖分
四邊形剖分
凸多邊形屬性
合併凸包
找共切線
凸多邊形交
臨界切線
凸多邊形向量和
最薄截面
最薄橫截帶
然後就講一下旋轉卡殼演算法思想:重點內容
簡單來說就是用一對平行線「卡」住凸包進行旋轉。
被一對卡殼正好卡住的對應點對稱為對踵點(如下圖)
可以證明對踵點的個數不超過3n/2個 也就是說對踵點的個數是o(n)的
對踵點的個數也是我們下面解決問題時間複雜度的保證
有兩種卡殼情況:
一、兩個平行線正好卡著兩個點
二、分別卡著一條邊和乙個點
在第二種情況中 我們可以看到 乙個對踵點和對應邊之間的距離比其他點到那條邊的距離要大
也就是乙個對踵點和對應邊所形成的三角形面積是最大的 下面我們會據此得到對踵點的簡化求法。
根據上面的第二種情況,我們可以得到下面的方法:
如果qa,qb是凸包上最遠兩點,必然可以分別過qa,qb畫出一對平行線。通過旋轉這對平行線,我們可以讓它和凸包上的一條邊重合,如圖中藍色直線,可以注意到,qa是凸包上離p和qb所在直線最遠的點。於是我們的思路就是列舉凸包上的所有邊,對每一條邊找出凸包上離該邊最遠的頂點,計算這個頂點到該邊兩個端點的距離,並記錄最大的值。
直觀上這是乙個o(n2)的演算法,和直接列舉任意兩個頂點一樣了。
然而我們可以發現 凸包上的點依次與對應邊產生的距離成單峰函式(如下圖:)
這個性質就很重要啦。
根據這個凸包的特性,我們注意到逆時針列舉邊的時候,最遠點的變化也是逆時針的,這樣就可以不用從頭計算最遠點,而可以緊接著上一次的最遠點繼續計算。於是我們得到了o(n)的演算法。這就是所謂的「旋轉」吧!
利用旋轉卡殼,我們可以在o(n)的時間內得到凸包的對鐘點中的長度最長的點對。
又由於最遠點對必然屬於對踵點對集合 ,那麼我們先求出凸包 然後求出對踵點對集合 然後選出距離最大的即可。
那麼具體的**就很容易實現了,利用叉積。
學習就要趁熱打鐵啦
一道模板題:poj 2187 beauty contes
ac**如下:
#include
#include
#include
#include
using
namespace
std;
const
int maxn=50000+7;
struct points
};typedef points vector;
vector operator -(points a,points b)
int n,m,maxdis;
points p[maxn],ch[maxn];
int cross(vector a,vector b)
bool cmp(points a,points b)
void convexhull()
int k=m;
for(int i=n-2;i>=0;--i)
if(n>1) m--;
} int dis(points a,points b)
void rotating_caliper()else
maxdis=max(maxdis,dis(ch[i],ch[j]));}}
}int main()
maxdis=-1;
if(n==2)else
cout
0;}
模板 旋轉卡殼
link 模板乙個。其實感覺說是求凸包的直徑倒不如說是求平面內最遠點對,畢竟它的輸入沒保證是個凸包,自己還要再求一遍啊 旋轉卡殼的思想十分優雅易懂,就是先證明平面內最近點對一定是凸包上兩點,再根據這個結論,列舉每一條邊的同時找出離線段最遠的點並更新答案即可。為了盡可能地降低找點的複雜度,對問題進行分...
旋轉卡殼部分模板
凸包直徑 旋轉卡殼凸包直徑詳解 計算凸包直徑,輸入凸包ch,頂點個數為n,按逆時針排列,輸出直徑的平方 int rotating calipers int n return ans 凸包間最小距離 struct point 建構函式 方便 編寫 p n q n typedef point point...
模板 凸包 旋轉卡殼
模板 凸包 旋轉卡殼 lrj 訓練指南 p272 對於個點按照 x 從小到大排序,再按照 y 點從小到大排序,刪除重複的點後,得到序列 p0,p1,p2.把 p0 和 p1 放入凸包。從p2開始,當新點在凸包 前進 方向的左邊時繼續,否則依次刪除最近加入凸包的點,直到新點在左邊 ps 判斷用叉積即可...