洛谷P2742 二維凸包

2021-10-02 10:58:17 字數 3207 閱讀 1425

有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

p12​p1

3​​×

p11​

p12​

​<=0

的判定,加入這個點可以構成凸包。(等於0是共線,也滿足條件可加入)

加入p14:p13p

14⃗×p

12p13⃗

>

0\vecp_}×\vecp_}>0

p13​p1

4​​×

p12​

p13​

​>

0,不符合凸包條件,凸包後退到p11和p12

但是p 12p

14⃗×p

11p12⃗

>

0\vecp_}×\vecp_}>0

p12​p1

4​​×

p11​

p12​

​>

0仍然成立,繼續後退

p 11p

14⃗×p

10p11⃗

<

0\vecp_}×\vecp_}<0

p11​p1

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 是我亂搞的符號,雖然我搞不懂為什麼是這樣,但是這...