凸包點集q的凸包(convex hull)是指乙個最小凸多邊形,滿足q中的點或者在多邊形邊上或者在其內。右圖中由紅色線段表示的多邊形就是點集q=的凸包。
頂點個數n
(1)排序:
在點集q中找最左下方的點p0,就是x座標和y座標都最小的點,其餘的點計算它們的極座標幅角,以幅角的非降序順序來排序,如果有幅角相同的,最接近p0的優先。(這是《acm程式設計培訓教程》上的排序方法,由於看不懂什麼是幅角,於是上網找了另一種排序方法,效果是一樣的,具體見附)
(2)掃瞄:
堆疊初始化為chs(n) = ,棧頂指標ps初始化為1,按排序好的點,從p1到pn-1掃瞄,如果pi (i=1...n-1)和chs棧頂的兩個元素(chs[sp-1],chs[sp])的三角形符號是正的,說明chs[sp-1],chs[sp],pi是逆時針方向,形成的邊是凸邊,所以可以把pi加入棧,sp++,繼續掃瞄後面的pi+1;如果三角形符號是負的,那chs[sp]不可能是凸包的極點,出棧,sp--,而pi仍舊是pi。下一輪仍舊是chs[sp-1],chs[sp], pi.
附:向量叉積
設有點p0(x0,y0),p1(x1,y1),p2(x2,y2).(p0p1),(p0p2)是共p0的兩條向量,叉積d = (p0p1)x(p0p2) = (x1-x0)*(y2-y0) - (x2-x0)*(y1-y0)
叉積的乙個非常重要性質是可以通過它的符號判斷兩向量相互之間的順逆時針關係:
若 d > 0 , 則(p0p1)在(p0p2)的順時針方向。
若 d < 0 , 則(p0p1)在(p0p2)的逆時針方向。(圖示方向)
若 d = 0 , 則(p0p1)與(p0p2)共線,但可能同向也可能反向。
過程如下:
#include
#include
#include
#include
#define n 20
#define inf 1e-6
typedef struct
point;
point points[n]; //點集
point chs[n]; //棧
int sp; //棧頂指標
//計算兩點之間距離
double dis(point a, point b)
//通過向量叉積求極角關係(p0p1)(p0p2)
//k > 0 ,p0p1在p0p2順時針方向上
double multi(point p0, point p1, point p2)
int cmp(const void *p, const void *q)
void convex_hull(int n)
{int i, k, d;
int miny = points[0].y, index = 0;
for(i=1; i
7凸包問題 Graham掃瞄法
點集q的凸包 convex hull 是指乙個最小凸多邊形,滿足q中的點或者在多邊形邊上或者在其內。右圖中由紅色線段表示的多邊形就是點集q 的凸包。頂點個數n 1 排序 在點集q中找最左下方的點p0,就是x座標和y座標都最小的點,其餘的點計算它們的極座標幅角,以幅角的非降序順序來排序,如果有幅角相同...
凸包(Graham掃瞄法構建)
ps 我的媽呀,心態 好像也不太難,看各種模板看的雲裡霧裡的,真的還是自己動手敲來的好,幾乎沒多久就懂的差不多了。乙個本該寒假就該掌握的知識,居然熬了我幾個小時。這一次還是很好的了解了凸包,以前看群裡學長們說,覺得好高大上,好難的樣子,仔細了解後發現其實也沒有想象中的那麼恐怖 凸包基本概念 這就是乙...
尋找凸包的graham 掃瞄法
1,點集q的凸包 convex hull 是指乙個最小凸多邊形,滿足q中的點或者在多邊形邊上或者在其內。2,凸包最常用的凸包演算法是graham掃瞄法和jarvis步進法。3,graham掃瞄法 首先,找到所有點中最左邊的 y座標最小的 如果y座標相同,找x座標最小的.以這個點為基準求所有點的極角 ...