凸包及其算法

概念

凸包:一个能够将所有给定点围住的最小周长封闭图形
稳定凸包:在当前组成凸包的点集 V 0 V_0 V0 中新增一个不在凸包上的点,形成新点集 V 1 V_1 V1,若可以使 V 1 V_1 V1 中所有点都在 V 1 V_1 V1 的点的凸包上,则这个凸包不稳定。反之,则是稳定凸包。

求解凸包

问题

给定在平面直角坐标系中 n n n 个点 P i ( x i , y i ) P_i(x_i,y_i) Pi(xi,yi),求解这些点的凸包。

思考

因为凸包是最小周长的封闭图形,所以凸包一定是由多条线段构成的,毕竟两点之间直线最短。

也就是说,凸包一定是多边形说了跟说了一样

暴力算法

可以发现,对于凸包的一条边,这条边所在的直线一定使得所有点都在其左边或者右边。

所以枚举两个点 P 0 , P 1 P_0, P_1 P0,P1,判断所有点是否在 P 0 P 1 P_0P_1 P0P1 同一边。

时间复杂度 O ( n 2 ) O(n^2) O(n2)

分治

横坐标最大和最小的两点一定在凸包上。而且这两点将凸包分为上凸和下凸。

然后分别对上凸包和下凸包用分治进行求解。

若是上凸包,假设当前分治到点 P l , P r P_l, P_r Pl,Pr 之间,则 P m i d P_{mid} Pmid 为在 P l P r P_lP_r PlPr 上方离 P l P r P_lP_r PlPr 最远的节点,然后继续分治 P l P m i d , P m i d P r P_lP_{mid}, P_{mid}P_r PlPmid,PmidPr

若是下凸包,则 P m i d P_{mid} Pmid 为在 P l P r P_lP_r PlPr 下方离 P l P r P_lP_r PlPr 最远的节点。其他同理。

时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

Graham扫描法

P 0 P_0 P0 y y y 坐标最小的点。(然后将 y y y 坐标最小的点从 P P P 中删除)

将除 P 0 P_0 P0 外点按照以 P 0 P_0 P0 为极点、任意一条从 P 0 P_0 P0 出发的射线为极轴的极坐标排序。(此处按逆时针方向排序)

然后将 P 0 P_0 P0 丢入当前凸包。

接下来假设 P P P 已经按照极坐标排序, D D D 表示凸包内的点( D D D 内点按照加入顺序排序,即 D 0 D_0 D0 是第一个加入的)。

将排好序的点依次访问,更新凸包,假设当前点为 P i P_i Pi,当前凸包内点为 D 0 , D 1 , . . . , D d D_0,D_1,...,D_d D0,D1,...,Dd

由于是逆时针排序的,所以 D D D 中点按顺序组成的每条边相对与上一条边一定往左偏。

我们判断 P i D d P_iD_d PiDd D d D d − 1 D_dD_{d -1} DdDd1 的关系。若 P i D d P_iD_d PiDd 相当于 D d D d − 1 D_dD_{d -1} DdDd1 往右偏,则 D d D_d Dd P i D d − 1 P_iD_{d-1} PiDd1 左侧,我们将 D d D_d Dd 删除,然后 d d d 减一。

P i D d P_iD_d PiDd 相当于 D d D d − 1 D_dD_{d -1} DdDd1 往左偏,则不需要删除。继续 P i + 1 P_{i+1} Pi+1

时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn)

你可能感兴趣的:(算法与数据结构,算法,c++)