Andrew 演算法(構造凸包)

2022-07-23 20:48:24 字數 2762 閱讀 2674

這是乙個基 \(graham\) 思想的又乙個演算法,我個人認為其中複雜度的改進應該是在\(sort\) 的 \(cmp\) 部分吧,

\(graham\) 的 \(cmp\) 部分需要對兩個點算出叉乘,甚至在某些情況還要算出兩個點的距離,這一步驟應該相對而言複雜度是較高的。

而 \(andrew\) 很好的避免了這一步驟,直接通過對點的 \(x, y\) 的簡單排序就可以實現乙個 \(nlogn\) 的演算法

這是第一遍 \(scan\),藍色的代表曾經走過,但是因為與後面的點構成凸包矛盾而進行過回溯。紅色的線代表這一趟掃瞄滿足條件的級邊,也就是構成凸包的下半部分的邊。

這是第二遍 \(scan\),綠色的代表曾經走過,但是因為與後面的點構成凸包矛盾而進行過回溯。黑色的線代表這一趟掃瞄滿足條件的級邊,也就是構成凸包的上半部分的邊。

\(sort\) 的時間是 \(o(nlogn)\) 兩趟 \(scan\) 的時間都是線性的,整地複雜度是 \(o(nlogn)\),但是我們認為這個演算法的時間複雜度是優於 \(graham\) 的,原因應該是我在開頭提到的把

p2742 [usaco5.1]圈奶牛fencing the cows /【模板】二維凸包

/*

凸包andrew演算法

*/#includeusing namespace std;

const double inf = 1e100;

const double eps = 1e-8;

const double pi = acos(-1.0);

const int n = 1e5 + 10;

int n, cnt, m;

int sgn(double x)

struct point

bool operator < (point t)

}p[n], ans[n], all[n];

point operator - (point a, point b)

double dis(point a, point b)

double cross(point a, point b)

void andrew()

// cout << p1 << endl;

// for(int i = 0; i < p1; i++)

// printf("%lf %lf %s\n", ans[i].x, ans[i].y, flag ? "false" : " true");

// }

// cout << p1 << endl;

p2 = p1;

for(int i = n - 2; i>= 0; i--)

// for(int i = 0; i < p2; i++)

// printf("%lf %lf\n", ans[i].x, ans[i].y);

// p2--;

p2--;

// for(int i = p1; i < p2; i++)

// printf("%lf %lf %s\n", ans[i].x, ans[i].y, flag ? "false" : " true");

// }

// cout << p2 << endl;

double target = 0.0;

for(int i = 0; i < p2; i++)

target += dis(ans[i], ans[i + 1]);

printf("%.2f\n", target);

}int main()

/*

凸包andrew演算法

*/#includeusing namespace std;

const double inf = 1e100;

const double eps = 1e-8;

const double pi = acos(-1.0);

const int n = 1e5 + 10;

int n, cnt, m;

int sgn(double x)

struct point

bool operator < (point t)

}p[n], ans[n], all[n];

point operator - (point a, point b)

double dis(point a, point b)

double cross(point a, point b)

void andrew()

p2 = p1;

for(int i = n - 2; i>= 0; i--)

p2--;

double target = 0.0;

for(int i = 0; i < p2; i++)

target += dis(ans[i], ans[i + 1]);

printf("%.2f\n", target);

}int main()

凸包 Andrew演算法

凸包的定義如下 在乙個點集d中,按一定順序選取子集q 使得q中所有點順次連線所構成的封閉凸多邊形包住d中所有點 可以形象地理解為 有許多個釘子釘在平面上,用一根牛皮筋把所有點包住 如下圖 andrew演算法是graham演算法的變種。其主要思想為把凸包上的點依次放入棧中,如果發現形成了凹多邊形 叉積...

凸包(Andrew演算法)模板

andrew演算法是graham的變種,相較graham,其更快,數值穩定性更好。藍書 struct nodep maxn ch maxn bool cmp node a,node b int cross node p0,node p1,node p2 凸包邊上可以有點,則 否則 int conve...

二維凸包 Andrew演算法

把給定點包圍在內部的 面積最小的凸多邊形 設向量 p x1,y1 q x2,y2 則 p q x1 y2 x2 y1 其結果是乙個由 0,0 p,q,p q 所組成的平行四邊形的 帶符號的面積,p q q p p q p q 叉積的乙個非常重要的性質是可以通過它的符號來判斷兩向量相互之間的順逆時針關...