凸包

简介

(本文只讨论二维凸包)

粗略地看,凸包是对凸多边形的另一种称呼。

更加准确地说,对于二维平面上给定的点集,其凸包为包含了点集且由点集中的点连接而成的凸多边形。

在解题时,一般询问与凸包周长或面积相关的极值问题。


前置知识

向量

如果实在没有接触过向量的概念,那么大致将其想象为一个箭头就行了。

我们一般用坐标\((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\)扫描法。

我们选定点集中的一个点为原点,然后将根据所有点与其连线的斜率从大到小排序。

一般我们倾向于选择左下角的点,但是点的选择几乎不造成影响。

此处有图

显然斜率最小的点在凸包的边上。

对于剩下的所有点,枚举此前所有的点,考虑加入后是否会出现内凹。如果出现内凹,显然此前存在非最优的选点。

此处有图

对于上图中的情况,选择虚线是更优的解。

我们可以通过维护一个单调栈来实现这个过程。

在上面的判断中,判断是否出现内凹有多种思路,其中通过叉乘判断是较快的。

若叉乘为负数,则内凹,反之外凸,结论显然。


代码

护城河的挖掘「USACO 2006」

posted @ 2019-08-18 16:33  Ilverene  阅读(554)  评论(0编辑  收藏  举报