问题重述
某大学ACM集训队,不久前向学校申请了一块空地,成为自己的果园。全体队员兴高采烈的策划方案,种植了大批果树,有梨树、桃树、香蕉……后来,发现有些坏蛋,他们暗地里偷摘果园的果子,被ACM集训队队员发现了。因此,大家商量解决办法,有人提出:修筑一圈篱笆,把果园围起来,但是由于我们的经费有限,必须尽量节省资金,所以,我们要找出一种最合理的方案。由于每道篱笆,无论长度多长,都是同等价钱。所以,大家希望设计出来的修筑一圈篱笆的方案所花费的资金最少。有人已经做了准备工序哦,统计了果园里果树的位置,每棵果树分别用二维坐标来表示,进行定位。现在,他们要求根据所有的果树的位置,找出一个n边形的最小篱笆,使得所有果树都包围在篱笆内部,或者在篱笆边沿上。
本题的实质:凸包问题。请使用蛮力法和分治法求解该问题。
问题分析
问题的本质为凸包问题,意图找出一个点集 X X X中处于最外围的子点集 S S S,使得 S S S构成的多边形边数最少。
形式化问题:现有点集 X = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) } X=\{(x_1,y_1),(x_2,y_2),\dots,(x_n,y_n)\} X={
(x1,y1),(x2,y2),…,(xn,yn)},其子集 S S S,满足 min { S 1 , S 2 , … , S m } , m = 1 , 2 , … , 2 n \min \{S_1,S_2,\dots ,S_m\},\space m=1,2,\dots,2^n min{
S1,S2,…,Sm}, m=1,2,…,2n, 且能完全包围 X X X.
此处的“完全包围 X X X”很难用笼统地用形式化的方式去定义,但我们能在算法的构建过程中的具体分析其数学意义。
算法分析
设计思想
要了解凸包,必须了解凸性的定义。概括来说,平面邻域中任意两点所在的线段上的点都在该邻域中,则该邻域具有凸性。
Divide & Conquer方法
- 将所有点按照 x x x轴升序排列顺序,最左侧的点 P 1 P_1 P1和最右侧的点 P n P_n Pn为点集的边界,故一定为凸包上的点。直线 P 1 P n ‾ \overline{P_1P_n} P1Pn 把点集分成了两部分,即 x x x 轴上面和下面两部分,分别叫做上包和下包。
对上包:求距离直线 P 1 P n ‾ \overline{P_1P_n} P1Pn 最远的点 P c P_c Pc ,即下图中的点 D D D。
] - 作直线 P 1 P c ‾ \overline{P_1P_c} P1Pc 、 P n P c ‾ \overline{P_nP_c} PnPc<