[13/07/19] 凸包学习笔记

所谓凸包,就是给你一堆点,让你找一个最小的凸多边形(二维),使其包含所有点。这个凸多边形就是这些点的凸包。可以理解为是用橡皮筋把很多钉子围住的状态。

  这些是凸包:

  这些不是:

  那么我们如何构造凸包呢?可以看出,如果我们按 x 排序的话,我甚至不想证明,最左和最右端点一定在凸包上。这样我们就可以把整个凸包分成上下两个”半凸包“来分别构造。

  对于半凸包而言,其实是有一个很强的性质的,就是对于这半边凸包上的边而言,斜率的变化是单调的。在上凸包的边斜率单调减,在下凸包的边斜率单调增,并且这也很好用三角不等式证明。

  那么我们准备逆用这个性质。 问题就转化为了:已知许多点的坐标,求出一条连接 p0pn 的路径,使路径权值单调。其中每条边的权值就是这条边的斜率。

  好的,果断使用单调栈。刚开始将 p0pn 加入,每次向栈内投入一个元素 (x0,y0),求出与当前栈顶元素 (x1y1) 和栈内下一位元素 (x2,y2) 的斜率并比较,若符合单调规则则加入,否则弹出栈顶元素,迭代 (x3,y3),重复上述操作直至回到初始点或满足条件。

  对于比较斜率的算法,大佬们使用的都是向量叉积,把两条边看做向量用 a,b 表示,然后通过求叉积——(x0x1,y0y1)(x0x2,y0y2) 的叉积为 (x0x1)(y0y2)(x0x2)(y0y1)——与零的大小判断。但作为蒟蒻怎么可能会这些奇怪的东西!所以我找了一种稍微通俗那么一点点的方式来解释。

  我们有两条边,一条斜率为 k1=y0y1x0x1,另一条斜率为 k2=y0y2x0x2 。作差法可得

k2k1=(y0y2)(x0x1)(y0y1)(x0x2)(x0x1)(x0x2)

  因为按 x 排序,所以 x0>x1>x2。则 k2k1 的符号与 (y0y2)(x0x1)(y0y1)(x0x2) 符号相同。

  这特么和叉积有什么区别?!

  至此凸包构造完毕。

posted @   四氧化二磷  阅读(155)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示