闵可夫斯基和
定义两个凸包 的闵可夫斯基和 。就是从原点向其中一个凸包连出的向量,平移到另一个凸包上的每一个点,最后构成的图形即为两个凸包的闵可夫斯基和。其中的第一个图形可以看做被缩到了原点, 中右下角(这里是指先是 坐标最小,再是 坐标最小的点)的点是 中两个右下角的点的坐标之和。
求法
对于两个凸包的情况,我们可以手模发现,最终形成的凸包 的每一条边都是凸包 中的一条边,可以用平行四边形来证明。由于在凸包上的每一条边,从最下面的那一条边开始,按照逆时针顺序,它们的极角是递增的。所以我们可以将 上的边依次比较极角,然后加入 中,从起始点开始每次加上那个边表示的向量。
对于多个凸包的情况,我们可以将所有的边放到一起进行排序,最后一起处理。
求凸包
(由于自己总是求不对凸包,这里写一下)
通常是先求出右下角的点,然后按照以该点为原点的其他点的极角序加入凸包。这里如果使用 的话,要注意精度问题;另一种判断方法是用叉积:若 ,则 在 的顺时针方向( 所在的直线的右边,视角为向量的方向);若 ,则在逆时针方向;若 ,则两个向量共线。这里要注意的是由于极角是到 轴的正半轴,所以要先比较两个向量是否同在 轴的上方或下方,然后再判断;如果两个向量方向相同,则要先加入距离右下角的点最远的的,因为一般情况下我们会将凸包上所有三点共线的点删掉,所以要这样做来防止删掉了我们要求的凸包上的点。
(防止自己记不住,再写一遍:)
由于在凸包上的连续三个点 按照逆时针排序的话,它们是满足 的,由于我们不要三点共线上的点,所以一般将 去掉。构建时维护一个栈,每次判断栈顶的下一位、栈顶和要加入的点是否满足条件,不满足就弹栈。
练习题
P8101 [USACO22JAN] Multiple Choice Test P
模板题(确信)。
题意:给定 组向量,每组向量有 个,每次你需要选择每一组中的一个向量,问最终这些向量的和到原点的距离的最大值。
解法:先将一组向量画出来,发现可能成为的点都在凸包上。然后考虑如何合并两组的答案,发现两组的答案其实是将其中一组的向量全部平移到另一组向量上,然后再求一次凸包上的点。这就和闵可夫斯基和一样,于是我们处理出每一组向量的凸包,然后求所有凸包的闵可夫斯基和就行了。
P4557 [JSOI2018] 战争
题意:给定两组点,有 次询问,每次问你将第二组点都加上一个向量 后,平面内是否存在一个点,满足它既被第一组的点中任意三点构成的三角形覆盖,又被第二组的点中的任意三点构成的三角形覆盖。
解法:首先先求出两组点构成的凸包,接着问题就变成了求两个凸包是否有交集,这种问题我们使用闵可夫斯基和来求解。题目问的是是否存在一个在凸包 中的点 平移 后与凸包 中的点 相同,即 ,移项得到 。于是我们将 中的每个点取反就得到了 ,然后求闵可夫斯基和就好了。
最后是判断一个点是否在凸包内,这里使用二分。将最后求得的凸包 的右下角的点平移到原点上,然后从原点向询问的点连一条边,找到凸包上的一条边,满足原点连向它的两个端点的向量的极角,包含了询问的点的极角。之后用叉积判断即可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· 2分钟学会 DeepSeek API,竟然比官方更好用!
· .NET 使用 DeepSeek R1 开发智能 AI 客户端
· DeepSeek本地性能调优
· 一文掌握DeepSeek本地部署+Page Assist浏览器插件+C#接口调用+局域网访问!全攻略