闵可夫斯基和
定义两个凸包 \(A,B\) 的闵可夫斯基和 \(C=\{a+b\mid a\in A,b\in B\}\) 。就是从原点向其中一个凸包连出的向量,平移到另一个凸包上的每一个点,最后构成的图形即为两个凸包的闵可夫斯基和。其中的第一个图形可以看做被缩到了原点,\(C\) 中右下角(这里是指先是 \(y\) 坐标最小,再是 \(x\) 坐标最小的点)的点是 \(A,B\) 中两个右下角的点的坐标之和。
求法
对于两个凸包的情况,我们可以手模发现,最终形成的凸包 \(C\) 的每一条边都是凸包 \(A,B\) 中的一条边,可以用平行四边形来证明。由于在凸包上的每一条边,从最下面的那一条边开始,按照逆时针顺序,它们的极角是递增的。所以我们可以将 \(A,B\) 上的边依次比较极角,然后加入 \(C\) 中,从起始点开始每次加上那个边表示的向量。
对于多个凸包的情况,我们可以将所有的边放到一起进行排序,最后一起处理。
求凸包
(由于自己总是求不对凸包,这里写一下)
通常是先求出右下角的点,然后按照以该点为原点的其他点的极角序加入凸包。这里如果使用 \(atna2(y,x)\) 的话,要注意精度问题;另一种判断方法是用叉积:若 \(\vec{AB}\times\vec{AC}<0\) ,则 \(\vec{AC}\) 在 \(\vec{AB}\) 的顺时针方向(\(\vec{AB}\) 所在的直线的右边,视角为向量的方向);若 \(>0\) ,则在逆时针方向;若 \(=0\) ,则两个向量共线。这里要注意的是由于极角是到 \(x\) 轴的正半轴,所以要先比较两个向量是否同在 \(x\) 轴的上方或下方,然后再判断;如果两个向量方向相同,则要先加入距离右下角的点最远的的,因为一般情况下我们会将凸包上所有三点共线的点删掉,所以要这样做来防止删掉了我们要求的凸包上的点。
(防止自己记不住,再写一遍:\(\vec{A}\times\vec{B}=A.x*B.y-A.y*B.x\))
由于在凸包上的连续三个点 \(P_1,P_2,P_3\) 按照逆时针排序的话,它们是满足 \(\vec{P_1P_2}\times\vec{P_2P_3}\ge0\) 的,由于我们不要三点共线上的点,所以一般将 \(=\) 去掉。构建时维护一个栈,每次判断栈顶的下一位、栈顶和要加入的点是否满足条件,不满足就弹栈。
练习题
P8101 [USACO22JAN] Multiple Choice Test P
模板题(确信)。
题意:给定 \(N\) 组向量,每组向量有 \(G_i\) 个,每次你需要选择每一组中的一个向量,问最终这些向量的和到原点的距离的最大值。
解法:先将一组向量画出来,发现可能成为的点都在凸包上。然后考虑如何合并两组的答案,发现两组的答案其实是将其中一组的向量全部平移到另一组向量上,然后再求一次凸包上的点。这就和闵可夫斯基和一样,于是我们处理出每一组向量的凸包,然后求所有凸包的闵可夫斯基和就行了。
题意:给定两组点,有 \(Q\) 次询问,每次问你将第二组点都加上一个向量 \((x_i,y_i)\) 后,平面内是否存在一个点,满足它既被第一组的点中任意三点构成的三角形覆盖,又被第二组的点中的任意三点构成的三角形覆盖。
解法:首先先求出两组点构成的凸包,接着问题就变成了求两个凸包是否有交集,这种问题我们使用闵可夫斯基和来求解。题目问的是是否存在一个在凸包 \(B\) 中的点 \(b\) 平移 \(w\) 后与凸包 \(A\) 中的点 \(a\) 相同,即 \(b+w=a\) ,移项得到 \(w=a-b\) 。于是我们将 \(B\) 中的每个点取反就得到了 \(-b\) ,然后求闵可夫斯基和就好了。
最后是判断一个点是否在凸包内,这里使用二分。将最后求得的凸包 \(C\) 的右下角的点平移到原点上,然后从原点向询问的点连一条边,找到凸包上的一条边,满足原点连向它的两个端点的向量的极角,包含了询问的点的极角。之后用叉积判断即可。
标签:原点,极角,笔记,凸包,闵可,夫斯基,vec,向量 From: https://www.cnblogs.com/Cyanwind/p/18337965