Minkowski和

来源:互联网 发布:bender软件 编辑:程序博客网 时间:2024/04/27 17:24

两个凸集的和(每两个不同集的x,y分别相加得新点)为凸集。

将两个凸集按同样时针求向量,极角排序后按向量走既得新凸集(但还需对应点平移)。

应用:求两凸集距离。

area

求新凸集面积。

不需平移,直接叉积。

这道题证明二分快排是可以卡的。

#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <ctime>struct point{       long long x,y,c;};const double eps=1e-6;point a[300000],b[3][300000],p[300000];int n,m,tot,t[3],st[3][300000];int cmper(const void *i,const void *j){    point *p=(point *)i,*q=(point *)j;    if (0==(p->y - q->y)) return (p->x-q->x);//    if (p->y == q->y) return p->x - q->x;    return p->y-q->y;}inline long long cross(point e,point r){       return ((e.x*r.y)-(e.y*r.x));}int check(int c,int i,int j,int k){    point u,v,w;    u=a[i],v=a[j],w=a[k];     point e,r;    e.x=v.x-u.x,e.y=v.y-u.y;    r.x=w.x-u.x,r.y=w.y-u.y;    long long kk=cross(e,r);    return (kk>=0) ? 1 : 0;}void work(int c,int s){     qsort(a+1,s,sizeof(a[1]),cmper);     memset(st[c],0,sizeof(st[c]));     t[c]=1;st[c][t[c]]=1;     int i,k;     for (i=2;i<=s;i++)     {         for (;(t[c]>1)&&(check(c,st[c][t[c]-1],st[c][t[c]],i));t[c]--) ;         st[c][++t[c]]=i;     }     k=t[c];     for (i=s-1;i>0;i--)     {         for (;(t[c]>k)&&(check(c,st[c][t[c]-1],st[c][t[c]],i));t[c]--) ;         st[c][++t[c]]=i;              }     if (s>1) t[c]--; }void init(){     scanf("%d%d\n",&n,&m);     int i;     for (i=1;i<=n;i++)     {         scanf("%I64d%I64d",&a[i].x,&a[i].y);//         b[1][i]=a[i];     }     scanf("\n");     work(1,n);     for (i=1;i<=n;i++) b[1][i]=a[i];     memset(a,0,sizeof(a));     for (i=1;i<=m;i++)     {         scanf("%I64d%I64d",&a[i].x,&a[i].y);//         b[2][i]=a[i];              }     scanf("\n");     work(2,m);     for (i=1;i<=m;i++) b[2][i]=a[i];      } long long equ(long long x){    if ((x>-eps)&&(x<eps)) return 1;    return 0;} void doit(int c){     int i;     for (i=2;i<=t[c];i++)     {         tot++;         p[tot].x=b[c][st[c][i]].x-b[c][st[c][i-1]].x;         p[tot].y=b[c][st[c][i]].y-b[c][st[c][i-1]].y;      if ((p[tot].x>0)&&((p[tot].y>0)||(equ(p[tot].y)))) p[tot].c=1;      if (((p[tot].x<0)||(equ(p[tot].x)))&&(p[tot].y>0)) p[tot].c=2;            if ((p[tot].x<0)&&((p[tot].y<0)||(equ(p[tot].y)))) p[tot].c=3;            if (((p[tot].x>0)||(equ(p[tot].x)))&&(p[tot].y<0)) p[tot].c=4;           }     tot++;      p[tot].x=b[c][st[c][1]].x-b[c][st[c][i-1]].x;      p[tot].y=b[c][st[c][1]].y-b[c][st[c][i-1]].y;      if ((p[tot].x>0)&&((p[tot].y>0)||(equ(p[tot].y)))) p[tot].c=1;      if (((p[tot].x<0)||(equ(p[tot].x)))&&(p[tot].y>0)) p[tot].c=2;            if ((p[tot].x<0)&&((p[tot].y<0)||(equ(p[tot].y)))) p[tot].c=3;            if (((p[tot].x>0)||(equ(p[tot].x)))&&(p[tot].y<0)) p[tot].c=4;       }inline int chek(point a,point b){    if (a.c<b.c) return 1 ;    else if (a.c>b.c) return 0;    long long k=cross(a,b);//    if (k<=0) return 0;    if (k>0) return 1;    return 0;}void qs(int l,int r){     int i=l,j=r;     point x=p[rand () % (r - l + 1) + l],c;//     long long xx=cross(x,x);          for (;i<=j;)     {         for (;chek(p[i],x);i++) ;         for (;chek(x,p[j]);j--) ;         if (i<=j)          {                     c=p[i],p[i]=p[j],p[j]=c;                     i++,j--;         }     }     if (i<r) qs(i,r);     if (l<j) qs(l,j); }int cmp(const void *i,const void *j){    point a=*(point*)i,b=*(point*)j;    if (a.c<b.c) return -1 ;    else if (a.c>b.c) return 1;    long long k=cross(a,b);//    if (k<=0) return 0;    if (k>0) return -1;    return 1;}void make(){//     qs(1,tot);     qsort(p+1,tot,sizeof(p[1]),cmp)  ;     int i;     long long ans=0;     point u,v;     u.x=0,u.y=0;     for (i=1;i<=tot;i++)     {         v.x=u.x+p[i].x;         v.y=u.y+p[i].y;         ans+=cross(u,v);         u=v;     }     if (ans<eps) ans=-ans;     printf("%I64d\n",ans); }int main(){    freopen("area.in","r",stdin);    freopen("area.out","w",stdout);        srand( int(time(NULL)));                                   init();        tot=0;        doit(1);        doit(2);        make();    return 0;}


原创粉丝点击