闵可夫斯基和,又称作闵可夫斯基加法,是两个欧几里得空间的点集的和,以德国数学家闵可夫斯基命名。(小知识:闵可夫斯基曾经做过爱因斯坦的老师。)
闵可夫斯基和是两个欧几里得空间的点集的和,也称为这两个空间的膨胀集,被定义为
\[ A + B=\{a+b|a \in A, b \in B \} \]根据闵可夫斯基和的定义,若集合元素所处代数系统满足阿贝尔群(加法可交换),则闵可夫斯基和本身也满足交换律:
\[ A+B=B+A \](以上参考自Baidu)
其实对于闵可夫斯基和,可以通俗的理解为,对于一个凸包\(A\)绕着凸包\(B\)转一圈:
对于求两个点集的闵可夫斯基和,通过肉眼观察,和理性分析,我们可以得出这么一个结论:两个凸包\(A\)和\(B\)上的边一定在闵可夫斯基和中出现。
然后我们就可以先求出两个点集的凸包,然后按极角排序后求闵可夫斯基和。
求凸包:
int Convexhull(geometric *p,ll l) { for(int i=2;i<=l;i++) { if(p[i].y<p[1].y)swap(p[1],p[i]); if(p[i].y==p[1].y&&p[i].x<p[1].x) swap(p[i],p[1]); } geometric k=p[1]; for(int i=1;i<=l;i++)p[i]=p[i]-k; sort(p+2,p+l+1,cmp); int top=0; geometric st[maxn]; st[++top]=p[1]; for(int i=2;i<=l;i++) { while(top>1&&cross(st[top-1],st[top],st[top],p[i])<0) top--; st[++top]=p[i]; } for(int i=1;i<=top;i++)p[i]=st[i]+k; p[top+1]=p[1]; return top; }
求闵可夫斯基和:
void Minkowski() { for(int i=1;i<=n;i++)s1[i]=p1[i+1]-p1[i]; for(int i=1;i<=m;i++)s2[i]=p2[i+1]-p2[i]; S[++cnt]=p1[1]+p2[1]; int i=1,j=1; while(i<=n&&j<=m) { cnt++; if(cross(origin,s1[i],origin,s2[j])>=0) S[cnt]=S[cnt-1]+s1[i++]; else S[cnt]=S[cnt-1]+s2[j++]; } while(i<=n) { cnt++; S[cnt]=S[cnt-1]+s1[i++]; } while(j<=m) { cnt++; S[cnt]=S[cnt-1]+s2[j++]; } }
[JSOI2018]战争