• 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
    ",(LL)fin);
      }
  • 相关阅读:
    一个进程间同步和通讯的 C# 框架
    C# 程序员最常犯的 10 个错误
    《C#并发编程经典实例》笔记
    C# BackgroundWorker 详解
    C# Excel导入导出
    List实现行转列的通用方案
    C# 开发者最经常犯的 8 个错误
    Intellij IDEA 查找接口实现类的快捷键
    target runtime com.genuitec.runtime.genuitec.jee60 is not defined
    java.io.WinNTFileSystem
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/6438149.html
Copyright © 2020-2023  润新知