【模板/经典题型】闵可夫斯基和

闵可夫斯基和是两个欧几里得空间的点集的和。
点集A与B的闵可夫斯基和就是{o|o=a+b},其中a属于A,b属于B。
求凸包之间的闵可夫斯基和的方法。
把两个凸包的每一条向量都抠出来,按照极角序排序构成新凸包即可。
注意点和向量的去重(向量相同斜率去重)。
还有个地方可以提一下:求多个凸包的闵可夫斯基和的时候可以直接全把边拿出来一块求,没有必要两个两个求。
具体实现的时候,找出最高且最靠左的点。
先把这个点加入答案,从这个点开始把所有向量跑一圈,最后去掉最后一个点即可(最后这个点会和第一个点重合)。

    pot P={-inf,-inf},Q={-inf,-inf},R={-inf,-inf};
    n=read(); 
    for(int i=1;i<=n;i++)
    {
        a[i].x=read();a[i].y=read();
        if(dcmp(a[i].y-P.y)==0&&dcmp(a[i].x-P.x)<0)P=a[i];
        if(dcmp(a[i].y-P.y)>0)P=a[i];
        if(i!=1)f[++cnt]=a[i]-a[i-1];if(i==n)f[++cnt]=a[1]-a[i];
    }
    n=read();
    for(int i=1;i<=n;i++)
    {
        b[i].x=read();b[i].y=read();
        if(dcmp(b[i].y-Q.y)==0&&dcmp(b[i].x-Q.x)<0)Q=b[i];
        if(dcmp(b[i].y-Q.y)>0)Q=b[i];
        if(i!=1)f[++cnt]=b[i]-b[i-1];if(i==n)f[++cnt]=b[1]-b[i];
    }
    n=read();
    for(int i=1;i<=n;i++)
    {
        c[i].x=read();c[i].y=read();
        if(dcmp(c[i].y-R.y)==0&&dcmp(c[i].x-R.x)<0)R=c[i];
        if(dcmp(c[i].y-R.y)>0)R=c[i];
        if(i!=1)f[++cnt]=c[i]-c[i-1];if(i==n)f[++cnt]=c[1]-c[i];
    }
    sort(f+1,f+cnt+1,cmp);
    pot k=P+Q+R;p[++tot]=k;
    for(int i=1;i<=cnt;i++)
    {
        k=k+f[i];
        if(i!=cnt&&dcmp(f[i].x*f[i+1].y-f[i].y*f[i+1].x)==0)continue;
        p[++tot]=k;
    }
    tot--;k=p[1];

猜你喜欢

转载自www.cnblogs.com/Creed-qwq/p/10317535.html