凸组合
n n n 元点集 P = { p 1 , p 2 , … , p n } P=\{p_1,p_2,\dots, p_n\} P = { p 1 , p 2 , … , p n } ,对于实数 λ 1 , λ 2 , … , λ n \lambda_1,\lambda_2,\dots, \lambda_n λ 1 , λ 2 , … , λ n ,满足:
λ i ≥ 0 , i = 1 , 2 , … , n \lambda_i\ge 0,i=1,2,\dots,n λ i ≥ 0 , i = 1 , 2 , … , n ;
∑ i = 1 n λ i = 1 \sum_{i=1}^n \lambda_i=1 ∑ i = 1 n λ i = 1 ;
那么称 ∑ i = 1 n λ i p i \sum_{i=1}^n \lambda_i p_i ∑ i = 1 n λ i p i 为点集 P P P 的一个凸组合,其中 p i p_i p i 是以原点为起点,以这个点为终点的向量。
凸包
n n n 元点集 P P P 的凸包,定义为所有 P P P 的凸组合构成的集合,形式化地:
C H ( P ) = { ∑ i = 1 n λ i p i ∣ λ i ≥ 0 , ∑ i = 1 n λ i = 1 } CH(P)=\left\{\sum_{i=1}^n \lambda_i p_i \Bigg| \lambda_i\ge 0,\sum_{i=1}^n \lambda_i=1 \right\}
C H ( P ) = { i = 1 ∑ n λ i p i λ i ≥ 0 , i = 1 ∑ n λ i = 1 }
也就是说,某一点 q q q 在凸包内部当且仅当它能被表示为 P P P 的某个凸组合。
凸集
一个点集 C C C 为凸集,当且仅当对于任意两个点 p , q ∈ C p,q\in C p , q ∈ C ,对任意的 λ ∈ ( 0 , 1 ) \lambda\in(0,1) λ ∈ ( 0 , 1 ) ,都有 λ p + ( 1 − λ ) q ∈ C \lambda p+(1-\lambda)q\in C λ p + ( 1 − λ ) q ∈ C 。
凸包是一个凸集
证明 P P P 的凸包是一个凸集:
不妨设 p = ∑ i = 1 n λ i p i p=\sum_{i=1}^n \lambda_i p_i p = ∑ i = 1 n λ i p i ,q = ∑ i = 1 n μ i p i q=\sum_{i=1}^n\mu_ip_i q = ∑ i = 1 n μ i p i ,那么任取一个 γ ∈ ( 0 , 1 ) \gamma\in (0,1) γ ∈ ( 0 , 1 ) ,有 γ p + ( 1 − γ ) q = ∑ i = 1 n [ γ λ i + ( 1 − γ ) μ i ] p i \gamma p+(1-\gamma)q=\sum_{i=1}^n [\gamma \lambda_i+(1-\gamma)\mu _i]p_i γ p + ( 1 − γ ) q = ∑ i = 1 n [ γ λ i + ( 1 − γ ) μ i ] p i
观察系数,γ ∈ ( 0 , 1 ) , λ i , μ i ≥ 0 \gamma\in (0,1),\lambda_i,\mu_i\ge 0 γ ∈ ( 0 , 1 ) , λ i , μ i ≥ 0 ,因此每一个系数都非负;并且 ∑ i = 1 n [ γ λ i + ( 1 − γ ) μ i ] = γ ∑ i = 1 n λ i + ( 1 − γ ) ∑ i = 1 n μ i = 1 \sum_{i=1}^n[\gamma \lambda_i+(1-\gamma)\mu_i]=\gamma\sum_{i=1}^n\lambda_i +(1-\gamma)\sum_{i=1}^n \mu_i=1 ∑ i = 1 n [ γ λ i + ( 1 − γ ) μ i ] = γ ∑ i = 1 n λ i + ( 1 − γ ) ∑ i = 1 n μ i = 1 。
所以 C H ( P ) CH(P) C H ( P ) 是一个凸集。证毕。
凸包是“最小”的凸集
何为最小?形式化地,证明对于任意的凸集 C C C ,如果 P ⊆ C P\subseteq C P ⊆ C ,那么 C H ( P ) ⊆ C CH(P)\subseteq C C H ( P ) ⊆ C :
任取 p ∈ C H ( P ) p\in CH(P) p ∈ C H ( P ) ,都存在一组 λ i \lambda_i λ i ,使得 p = ∑ i = 1 n λ i p i p=\sum_{i=1}^n\lambda_ip_i p = ∑ i = 1 n λ i p i ,下面我们用数学归纳法证明,形如这样的 p ∈ C p\in C p ∈ C 。
设其中有 k k k 个 λ i \lambda_i λ i 不为零,因为这些 λ i \lambda_i λ i 的和是 1 1 1 ,那么 k ≥ 1 k\ge 1 k ≥ 1 。下设不为零的 λ i \lambda_i λ i 分别为 λ j 1 , λ j 2 , … , λ j k \lambda_{j_1},\lambda_{j_2},\dots,\lambda_{j_k} λ j 1 , λ j 2 , … , λ j k 。当 k = 1 , 2 k=1,2 k = 1 , 2 时,根据定义有 p ∈ C p\in C p ∈ C 。
若 k = k 0 k=k_0 k = k 0 时,命题成立,那么 k = k 0 + 1 k=k_0+1 k = k 0 + 1 时,因为 k ≥ 2 k\ge 2 k ≥ 2 ,所以显然不可能有一个 λ = 1 \lambda=1 λ = 1 ,并且:
p = λ j k p j k + ∑ i = 1 k − 1 λ j i p j i = λ j k p j k + ( 1 − λ j k ) ∑ i = 1 k − 1 λ j i 1 − λ j k p j i \begin{aligned}
p&=\lambda_{j_k}p_{j_k}+\sum_{i=1}^{k-1} \lambda_{j_i}p_{j_i}\\
&=\lambda_{j_k}p_{j_k}+(1-\lambda_{j_k})\sum_{i=1}^{k-1}\frac{\lambda_{j_i}}{1-\lambda_{j_k}} p_{j_i}
\end{aligned}
p = λ j k p j k + i = 1 ∑ k − 1 λ j i p j i = λ j k p j k + ( 1 − λ j k ) i = 1 ∑ k − 1 1 − λ j k λ j i p j i
结合 ∑ i = 1 k λ j i = 1 \sum_{i=1}^k \lambda_{j_i}=1 ∑ i = 1 k λ j i = 1 ,我们有 ∑ i = 1 k − 1 λ j i 1 − λ j k = 1 \sum_{i=1}^{k-1}\cfrac{\lambda_{j_i}}{1-\lambda_{j_k}}=1 ∑ i = 1 k − 1 1 − λ j k λ j i = 1 。由归纳假设,∑ i = 1 k − 1 λ j i 1 − λ j k p j i ∈ C \sum_{i=1}^{k-1}\cfrac{\lambda_{j_i}}{1-\lambda_{j_k}}p_{j_i}\in C ∑ i = 1 k − 1 1 − λ j k λ j i p j i ∈ C ,把它看成一个整体后,用定义可以得知 p ∈ C p\in C p ∈ C 。证毕。
Andrew 算法
为了方便行文,我们引入一个记号 Δ ( A , B , C ) = ( x B − x A ) ( y C − y A ) − ( x C − x A ) ( y B − y A ) \Delta(A,B,C)=(x_B-x_A)(y_C-y_A)-(x_C-x_A)(y_B-y_A) Δ ( A , B , C ) = ( x B − x A ) ( y C − y A ) − ( x C − x A ) ( y B − y A ) ,也就是 A B AB A B 和 A C AC A C 的叉积。
算法流程如下:
将点集 P P P 按照 x x x 为第一关键字、y y y 为第二关键字的字典序升序排序;
维护一个栈 S S S ,顺序遍历 P P P 中节点,假设当前遍历到 p i p_i p i :
若 ∣ S ∣ ≤ 1 |S|\le 1 ∣ S ∣ ≤ 1 ,直接将 p i p_i p i 入栈;
否则,设 A A A 为栈顶下一个元素,B B B 为栈顶元素,如果 Δ ( A , B , p i ) > 0 \Delta (A,B,p_i)>0 Δ ( A , B , p i ) > 0 ,那么 p i p_i p i 入栈,否则弹出栈顶元素,重复上一步。
遍历完成后得到下凸壳,反方向遍历一遍得到上凸壳。按照算法的执行逻辑,不难看出 p 1 , p n p_1,p_n p 1 , p n 一定是下凸壳的起点和终点、上凸壳的终点和起点。
于是我们得到了一个逆时针的、首尾相接的边的多边形。
设 C 1 , C 2 , … , C m C_1,C_2,\dots,C_m C 1 , C 2 , … , C m 为这个多边形的顶点。为了简化行文,我们令 C m + 1 = C 1 C_{m+1}=C_1 C m + 1 = C 1 。
下证所有多边形内部的点构成的集合 C C C ,是原点集 P P P 的凸包 C H ( P ) CH(P) C H ( P ) 。
形式化地,集合 C C C 被定义为:
C = { Q ∈ R 2 ∣ ∀ i ∈ [ 1 , m ] , Δ ( C i , C i + 1 , Q ) ≥ 0 } C=\left\{Q\in \mathbb R^2\mid \forall i\in[1,m],\Delta(C_i,C_{i+1},Q)\ge 0\right\}
C = { Q ∈ R 2 ∣ ∀ i ∈ [ 1 , m ] , Δ ( C i , C i + 1 , Q ) ≥ 0 }
要证明 C = C H ( P ) C=CH(P) C = C H ( P ) ,我们只能证明这两个集合互相包含。
P 是 C 的子集
我们将通过数学归纳法证明这一结论,我们将要证明:任取 P P P 中的一个点 p p p ,对于任意 i ∈ [ 1 , m − 1 ] i\in [1,m-1] i ∈ [ 1 , m − 1 ] ,都有 Δ ( C i , C i + 1 , p ) ≥ 0 \Delta(C_i,C_{i+1},p)\ge 0 Δ ( C i , C i + 1 , p ) ≥ 0 。
为了避免讨论 x x x 相同的情况,我们给所有的点做一个线性变换,让每一个点都左乘变换矩阵 T = [ 1 ε 0 1 ] T=\begin{bmatrix}1&\varepsilon\\0&1\end{bmatrix} T = [ 1 0 ε 1 ] ,显然 det ( T ) = 1 \det(T)=1 det ( T ) = 1 ,通过简单的代数展开可以得到,Δ ( A , B , C ) ≥ 0 \Delta(A,B,C)\ge 0 Δ ( A , B , C ) ≥ 0 当且仅当 Δ ( T A , T B , T C ) ≥ 0 \Delta(TA,TB,TC)\ge 0 Δ ( T A , TB , TC ) ≥ 0 。由于点集是有限的,我们总能取到一个 ε \varepsilon ε ,使得变换后 x x x 互不相同,并且变换之后仍然保持字典序升序。
一旦允许了这样的事情之后,这个证明就变得及其简单了:当我们处理下凸壳,进行弹出栈的操作时,每一段横坐标对应的新的斜率总会比原来的斜率更小,从而这个边界的每一个点对应的 y y y 坐标都在减小。通过归纳假设,我们可以断定原先的点 y y y 坐标必然仍然 $\ge $ 边界的 y y y 坐标。
通过代数变形可以得知这和 Δ ≥ 0 \Delta\ge 0 Δ ≥ 0 是等价的,又因为对原图的任意三个点 Δ ( A , B , C ) ≥ 0 \Delta(A,B,C)\ge 0 Δ ( A , B , C ) ≥ 0 当且仅当 Δ ( T A , T B , T C ) ≥ 0 \Delta(TA,TB,TC)\ge 0 Δ ( T A , TB , TC ) ≥ 0 ,所以我们证明了对于下凸壳上的所有点, Δ ( C i , C i + 1 , p ) ≥ 0 \Delta(C_i,C_{i+1},p)\ge 0 Δ ( C i , C i + 1 , p ) ≥ 0 恒成立。
对于上凸壳也是同理,因此 P ⊆ C P\subseteq C P ⊆ C 。
CH(P) 是 C 的子集
我们可以先给出一个结论,对任意凸组合,都有 Δ ( A , B , ∑ λ p ) = ∑ λ Δ ( A , B , p ) \Delta(A,B,\sum \lambda p)=\sum \lambda\Delta(A,B,p) Δ ( A , B , ∑ λ p ) = ∑ λ Δ ( A , B , p ) 。
这个证明比较麻烦,但是只是中学数学的公因式消消乐,本文不做过多阐述。
有了上面这个公式,就可以直接得到:任取 p , q ∈ C p,q\in C p , q ∈ C ,任取 λ ∈ [ 0 , 1 ] \lambda\in[0,1] λ ∈ [ 0 , 1 ] ,对于所有的 C i C i + 1 C_iC_{i+1} C i C i + 1 ,都有 Δ ( C i , C i + 1 , λ p + ( 1 − λ ) q ) = λ Δ ( C i , C i + 1 , p ) + ( 1 − λ ) Δ ( C i , C i + 1 , q ) ≥ 0 \Delta(C_i,C_{i+1},\lambda p+(1-\lambda)q)=\lambda \Delta(C_i,C_{i+1},p)+(1-\lambda)\Delta(C_i,C_{i+1},q)\ge 0 Δ ( C i , C i + 1 , λ p + ( 1 − λ ) q ) = λ Δ ( C i , C i + 1 , p ) + ( 1 − λ ) Δ ( C i , C i + 1 , q ) ≥ 0 ,因此 C C C 是一个凸集。
我们之前证明了,如果 C C C 是凸集,并且 P ⊆ C P\subseteq C P ⊆ C ,就有 C H ( P ) ⊆ C CH(P)\subseteq C C H ( P ) ⊆ C 。
C 是 CH(P) 的子集
这个命题的意思就是要我们证明,C C C 中任意一个点都可以表示成 P P P 中点的凸组合。
同样是给每一个点都左乘变换矩阵 T T T ,保证 x x x 互不相同之后来研究。
对于 C C C 中任意一个点 Q ( x , y ) Q(x,y) Q ( x , y ) ,总可以在下凸包找到 x i ≤ x ≤ x i + 1 x_i\le x\le x_{i+1} x i ≤ x ≤ x i + 1 ,那么过 Q Q Q 引一条铅垂线,与下面这个边的交点是可以被边的顶点用凸组合表示的,对于上凸包同理,那么这两个交点进一步可以用凸组合表示出 Q Q Q 。我承认这里没有那么严谨,民科轻喷。
因此 C ⊆ C H ( P ) C\subseteq CH(P) C ⊆ C H ( P ) 。