Minkowski sum

BZOJ2564

将两个凸包的边按极角顺序合并即可

#include <cstdio>
#include <cmath>
#include <algorithm>
#define LDB long double
#define LL long long 
using namespace std;
 
  const LDB eps=1e-6;
  int totcnt=0,n,m;
 
  struct data{
    LDB x,y,alp;
  }a[500011],tmp[500011],sta[500011],ans[500011];
   
  inline data operator - (const data&a,const data&b) {return (data){a.x-b.x,a.y-b.y,a.alp};}
 
  LL X(data a,data b){
      return((LL)a.x*(LL)b.y-(LL)a.y*(LL)b.x);
  }  
   
  LDB dis(data a,data b){
      return(sqrt((long double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))));
  }
 
  int mycomp(const data&aa,const data&b){
      if (X(aa-a[1],b-a[1])>0) return(1);
      if (X(aa-a[1],b-a[1])<0) return(0);
      return(dis(a[1],aa)>dis(a[1],b));
  }
   
  int mycomp2(const data&a,const data&b){
    return(a.alp<b.alp);
  }
 
  void graham(int n){
    int xmini=1e9,ymini=1e9;
    int po;
    for (int i=1;i<=n;i++){
        if (ymini>tmp[i].y||(ymini==tmp[i].y&&tmp[i].x<xmini)){
          xmini=tmp[i].x;ymini=tmp[i].y;    
          po=i;
      }
    }
    data t=tmp[po];tmp[po]=tmp[1];tmp[1]=t;
    a[1].x=xmini;a[1].y=ymini;
    sort(tmp+2,tmp+n+1,mycomp);
     
    int cnt=1;
    tmp[1].x=-1e9;tmp[1].y=-1e9;
    for (int i=2;i<=n;i++)
      if (X(tmp[i]-tmp[1],tmp[i-1]-tmp[1])!=0||i==2)
        a[++cnt]=tmp[i];                                               
    n=cnt;    
     
    int top=0;
    for (int i=1;i<=n;i++){
      while (top>=2&&X(sta[top]-sta[top-1],a[i]-sta[top-1])<-eps) 
        top--;
      sta[++top]=a[i];      
    }
     
    for (int i=2;i<=top;i++) ans[++totcnt]=sta[i]-sta[i-1];
    ans[++totcnt]=sta[1]-sta[top];
  }
 
  int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%Lf%Lf",&tmp[i].x,&tmp[i].y);
    graham(n);
    for (int i=1;i<=m;i++) scanf("%Lf%Lf",&tmp[i].x,&tmp[i].y);
    graham(m);
    
    for (int i=1;i<=totcnt;i++) ans[i].alp=atan2(ans[i].y,ans[i].x);
    sort(ans+1,ans+totcnt+1,mycomp2);
    LL fin=0;
    data o;o.x=o.y=0;
    for (int i=1;i<=totcnt;i++){
      data t;t.x=o.x+ans[i].x;t.y=o.y+ans[i].y;
      fin+=X(o,t);
      o=t;      
    }
    printf("%lld\n",(LL)fin);
  }

 

posted @ 2017-02-24 13:18  z1j1n1  阅读(957)  评论(0编辑  收藏  举报