有n個點,求凸包長度,0<=n<=10000
前置知識:向量的外積/叉積,用於判斷新加入的點能否與原本構成凸殼。
a ⃗=
(x1,
y1),
b⃗=(
x2,y
2)\vec=(x1,y1),\vec=(x2,y2)
a=(x1,
y1),
b=(x
2,y2)a⃗
×b⃗=
x1y2
−y1x
2\vec×\vec=x1y2-y1x2
a×b=x1
y2−y
1x2結果的正負性取決於右手定則,垂直紙面向外為正。
凸包的定義是包含所有點的最小凸多邊形,可以考慮點都是平面上的釘子,然後用乙個有彈性的皮筋從外部圍住它們,皮筋會縮緊,使多邊形最小,並且最「外」的釘子集合確定了這個圖形是凸的。
用的是andrew演算法,求凸殼分為了上下兩部分。每新加入乙個點,就判斷和前兩個點的延伸方向是否能構成凸殼,若能則加入;若不能則前兩個點後退,直到能將這個新點加入為止(後退而不計算的點被包含在了內部
)
演算法首先將所有點從小到大排序,x為第一關鍵字,y為第二關鍵字
從左到右求下凸殼
先加入序列中的前兩個點,開始遞推。
下面是一般性的**,如果新加入的點是這樣:
下面應該加入p13了,經過p12p
13⃗×p
11p12⃗
<=0
\vecp_}×\vecp_}<=0
p12p1
3×
p11
p12
<=0
的判定,加入這個點可以構成凸包。(等於0是共線,也滿足條件可加入)
加入p14:p13p
14⃗×p
12p13⃗
>
0\vecp_}×\vecp_}>0
p13p1
4×
p12
p13
>
0,不符合凸包條件,凸包後退到p11和p12
但是p 12p
14⃗×p
11p12⃗
>
0\vecp_}×\vecp_}>0
p12p1
4×
p11
p12
>
0仍然成立,繼續後退
p 11p
14⃗×p
10p11⃗
<
0\vecp_}×\vecp_}<0
p11p1
4×
p10
p11
<
0,加入14
同色的表示進行過判斷,現在p12和p13都落入了凸包的內部,凸包路徑變成了p9→p10→p11→p14
求同理運用一遍,從右到左,即可求出上凸殼(**中我做了reverse處理,將上凸殼翻轉成了下凸殼)
#include
#include
#include
#include
#include
#include
#include
using
namespace std;
struct point
point
(double a,
double b):x
(a),
y(b)
double x, y;
intdcmp
(double x)
//誤差取等
bool
operator
<
(const point& other)
//為了sort
else
}bool
operator==(
const point& other)
//為了unique};
struct vect//向量
//從點構造向量
double
cross
(vect other)
//叉積};
vector v;
//存所有點,並進行從小到大排序
int line[
10005
],ptr=0;
//儲存凸殼路徑
void
convex()
//求凸殼
}double
dis(point& a, point& b)
intmain()
sort
(v.begin()
, v.
end())
; v.
resize
(unique
(v.begin()
, v.
end())
- v.
begin()
);//去重點
if(n ==
0|| n ==
1)cout <<
"0.00"
;else
if(n ==
2)cout << fixed <<
setprecision(2
)<<
dis(v[0]
, v[1]
);double ans =0;
convex()
;for
(int i =
1; i < ptr; i++
) ptr =0;
reverse
(v.begin()
, v.
end())
;//反轉,等效於反向求凸殼
convex()
;for
(int i =
1; i < ptr; i++
) cout <
setprecision(2
)<< ans;
return0;
}
參考了劉汝佳的《演算法競賽入門經典-訓練指南》
——————————2020.1.31————————————
重構了**,加入了凸包的介紹
洛谷P2742 模板 二維凸包
求凸包 andrew演算法 首先按照 x 為第一關鍵字,y 為第二關鍵字從小到大排序,並刪除重複的點 用棧維護凸包內的點 1 把 p 1,p 2 放入棧中 2 若 p 在直線 p p 的右側,則不斷的彈出棧頂,直到該點在直線左側 3 此時我們已經得到了下凸包,那麼反過來從 p n 再做一次即可得到下...
二維凸包演算法
部落格參考 謝謝 chao xun 把凸包寫的這麼詳細。關於凸包的問題的解決的最初思路是這樣的。1 找到乙個基準點 必須在凸邊上 2 以基準點做射線,然後將該射線向固定方向旋轉,直到接觸到乙個新的點。3 以 2 中找到的點作為新的基準點,作射線繼續朝著一開始的固定的方向旋轉 4 反覆重複2,3直到最...
題解 二維凸包
呵呵呵複習一下這個東西免得做到計算幾何連暴力都不會嚶嚶嚶 免得到時候寫斜率優化結果凸包不會了嚶嚶嚶 數學走起 vec x 1,y 1 vec x 2,y 2 shadow times vec x 1y 2 x 2y 1 根據右手螺旋定則。shadow 是我亂搞的符號,雖然我搞不懂為什麼是這樣,但是這...