這部分沒啥好講的。點可以使用座標表示,向量可以使用點表示。
這裡記錄一些我知道的基礎知識。
對於向量\(a(x,y)\),其長度記為\(|a|=\sqrt\)
對於兩個向量 \(a(x_1,y_1),b(x_2,y_2)\) 他們的叉積是\(a\times b=x_1\cdot y_2-x_2\cdot y_1\)。叉積的絕對值還等於以這兩個向量為鄰邊的平行四邊形面積,即\(|a|\cdot|b|\cdot\sin\theta\),其中\(\theta\)是他們的夾角。叉積的正負號由右手螺旋定則確定。
對於兩個向量 \(a(x_1,y_1),b(x_2,y_2)\) 他們的點積是 \(a\cdot b=x_1\cdot y_1+x_2\cdot y_2=|a|\cdot|b|\cdot\cos\theta\),其中\(\theta\)是他們的夾角。
首先將所有點按照 \(x\) 軸為第一關鍵字,\(y\) 軸為第二關鍵字排序,用單調棧維護凸包即可。判斷是否是凸的可以使用叉積判斷。
#include #include #include using namespace std;
const int n = 1e5 + 5;
const double eps = 1e-10;
bool eql(double x, double y)
struct dot
dot operator-(const dot &d) const
double operator^(const dot &d) const
bool operator
} dt[n];
double dis(dot x, dot y)
int n, stk[n], tp;
bool vis[n];
int main()
vis[1] = 0;
//在圍下凸殼的時候需要用 1號點再彈出一些點
int nb = tp;
for (int i = n; i >= 1; --i)
double ans = 0;
for (int i = 1; i <= tp; ++i)
ans += dis(dt[stk[i]], dt[stk[i % tp + 1]]);
printf("%.2lf\n", ans);
return 0;
}
模板
求出凸包。每一條邊找到乙個點使得這個點距離這條邊最遠,這條邊的兩個端點和那個找到的點更新答案。至於如何找到那個點,我們發現凸包上的點和這個線段的距離是單峰的(峰是最值),所以考慮使用雙指標的方式解決問題。
注:乙個點和其他點的距離並不單調。因為有可能出現這種情況:你發現中間這個線非常短,而兩邊的特別長。
另外還需要特判只有兩個點的情況,否則會死迴圈。
#include #include #include using namespace std;
const int n = 5e4 + 5;
struct dot
dot operator-(const dot &d) const
int operator*(const dot &d) const
bool operator
} dt[n];
int dis(dot a, dot b)
int n, stk[n];
bool use[n];
int main()
use[i] = 1;
stk[++tp] = i;
} use[1] = 0;
int rec = tp;
for (int i = n; i >= 1; --i)
if (tp == 3)
int ans = 0, pt = 1;
for (int i = 1; i < tp; ++i)
printf("%d\n", ans);
return 0;
}
計算幾何學習筆記
基礎部分 include using namespace std define type double define vector point define eps 1e 8 const double pi 3.14159265358979323 type deg2red type deg type...
計算幾何學習筆記
計算幾何是什麼東西?能吃嗎?給定 n 個點 x i,yi 問 歐幾里得 距離最近的點對。如果用樸素的兩兩枚舉,需要o n2 的時間。考慮用分治法,先將點按照先 x 後 y排序。考慮對一段點 l r 的處理。在 放一根平行於y軸的線,其左邊的答案為a,右邊為b,設 min a,b 考慮如果有跨這條線的...
計算幾何學習筆記
計算幾何基本採用向量來表示點 線 麵等基本元素,而非我們平時常用的解析式。向量的基礎運算法則 給定兩個向量 p x 1,y 1 q x 2,y 2 加法 p q x 1 x 2,y 1 y 2 減法 p q x 1 x 2,y 1 y 2 數乘 lambda p lambda x 1,lambda ...