凸包
简介
(本文只讨论二维凸包)
粗略地看,凸包是对凸多边形的另一种称呼。
更加准确地说,对于二维平面上给定的点集,其凸包为包含了点集且由点集中的点连接而成的凸多边形。
在解题时,一般询问与凸包周长或面积相关的极值问题。
前置知识
向量
如果实在没有接触过向量的概念,那么大致将其想象为一个箭头就行了。
我们一般用坐标\((x,y)\)表示向量,意为从原点指向\((x,y)\)的箭头。
向量运算
向量的加法和减法结果均为向量:
\((x_1,y_1)±(x_2,y_2)=(x_1±x_2,y_1±y_2)\)
向量的乘法分为两种,点乘和叉乘,结果均为实数:
点乘表示向量\(a\)在向量\(b\)上的投影长度,\((x_1,y_1)*(x_2,y_2)=x_1y_1+x_2y_2\)
叉乘表示向量\(a\)和向量\(b\)共起点时组成的平行四边形面积,\((x_1,y_1)\land(x_2,y_2)=x_1y_2-x_2y_1\)
向量没有除法。
实现思路
实现采用的是\(Graham\)扫描法。
我们选定点集中的一个点为原点,然后将根据所有点与其连线的斜率从大到小排序。
一般我们倾向于选择左下角的点,但是点的选择几乎不造成影响。
显然斜率最小的点在凸包的边上。
对于剩下的所有点,枚举此前所有的点,考虑加入后是否会出现内凹。如果出现内凹,显然此前存在非最优的选点。
对于上图中的情况,选择虚线是更优的解。
我们可以通过维护一个单调栈来实现这个过程。
在上面的判断中,判断是否出现内凹有多种思路,其中通过叉乘判断是较快的。
若叉乘为负数,则内凹,反之外凸,结论显然。