zoukankan      html  css  js  c++  java
  • 【模板】旋转卡壳求双凸包最小距离——poj3608

    求两个凸包间的最小距离,最大距离,都是用同一种思路

    最大距离:枚举凸包A的每条边,然后去B找对踵点,求的是点到点的最短距离

    最小距离:比最大距离稍复杂一点,枚举凸包A的每条边,去B找对踵点,如果只有一个对踵点,那么求点到线段最短距离

                                      如果有两个对踵点,那么求线段到线段的最短距离(需要改动一下disSS函数)

    poj上的c++和G++是不一样的。。

    disSS函数不用判线段相交了

    db disSS(point k1,point k2,point k3,point k4){
        return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2)));
    }
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    typedef double db;
    const db eps=1e-8;
    const db pi=acos(-1.0);
    int sign(db k){
        if (k>eps) return 1; else if (k<-eps) return -1; return 0;
    }
    int cmp(db k1,db k2){return sign(k1-k2);}
    int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内 
    struct point{
        db x,y;
        point(){}
        point(db x,db y):x(x),y(y){}
        point operator + (const point &k1) const{return point(k1.x+x,k1.y+y);}
        point operator - (const point &k1) const{return point(x-k1.x,y-k1.y);}
        point operator * (db k1) const{return point(x*k1,y*k1);}
        point operator / (db k1) const{return point(x/k1,y/k1);}
        bool operator < (const point k1) const{
            int a=cmp(x,k1.x);
            if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
        }
        db abs(){return sqrt(x*x+y*y);}
        db abs2(){return x*x+y*y;}
        db dis(point k1){return ((*this)-k1).abs();}
    };
    int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
    db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
    db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} 
    
    point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影 
        point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
    }
    int intersect(db l1,db r1,db l2,db r2){
        if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
    }
    int checkSS(point k1,point k2,point k3,point k4){
        return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
        sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
        sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
    }
    db disSP(point k1,point k2,point q){
        point k3=proj(k1,k2,q);
        if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2));
    }
    db disSS(point k1,point k2,point k3,point k4){
        return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2)));
    }
    
    int onS(point k1,point k2,point q){return inmid(k1,k2,q)&&sign(cross(k1-q,k2-k1))==0;}
    int checkconvex(vector<point>A){ //判断是否是凸包
        int n=A.size(); A.push_back(A[0]); A.push_back(A[1]);
        for (int i=0;i<n;i++) if (sign(cross(A[i+1]-A[i],A[i+2]-A[i]))==-1) return 0;
        return 1;
    }
    vector<point> ConvexHull(vector<point>A,int flag=1){ // 求凸包:flag=0 不严格 flag=1 严格 
        int n=A.size(); vector<point>ans(n*2); 
        sort(A.begin(),A.end()); int now=-1;
        for (int i=0;i<A.size();i++){
            while (now>0&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
            ans[++now]=A[i];
        } int pre=now;
        for (int i=n-2;i>=0;i--){
            while (now>pre&&sign(cross(ans[now]-ans[now-1],A[i]-ans[now-1]))<flag) now--;
            ans[++now]=A[i];
        } ans.resize(now); return ans;
    }
    
    db ConvexMinDis(vector<point> a,vector<point> b){
        db Min=1e16;
        a.push_back(a[0]);b.push_back(b[0]);
        db ymin=1e16,ymax=-1e16;
        int p,q;
        for(int i=0;i<a.size()-1;i++)
            if(a[i].y<ymin)ymin=a[i].y,p=i;
        for(int i=0;i<b.size()-1;i++)
            if(b[i].y>ymax)ymax=b[i].y,q=i;
        
        db tmp;
        for(int i=0;i<a.size()-1;i++){//枚举a凸包上的边(p,p+1),比较b凸包上点q,q+1 
            while(sign(tmp=cross(a[p+1]-a[p],b[q+1]-a[p])-cross(a[p+1]-a[p],b[q]-a[p]))>0){
                q++;
                if(q==b.size()-1)q=0;
            }
            if(sign(tmp)<0)Min=min(Min,disSP(a[p],a[p+1],b[q]));//点到线段的距离 
            else Min=min(Min,disSS(a[p],a[p+1],b[q],b[q+1]));//线段到线段的距离 
            p++;
            if(p==a.size()-1)p=0;
        }
        return Min;
    } 
    
    int n,m;
    vector<point> v1,v2;
    
    int main(){
        while(cin>>n>>m && n && m){
            v1.clear();
            v2.clear();
            for(int i=1;i<=n;i++){
                point p;
                scanf("%lf%lf",&p.x,&p.y);
                v1.push_back(p);
            }
            for(int i=1;i<=m;i++){
                point p;
                scanf("%lf%lf",&p.x,&p.y);
                v2.push_back(p);
            }
            vector<point>con1=ConvexHull(v1,1);
            vector<point>con2=ConvexHull(v2,1);
            printf("%.5f
    ",min(ConvexMinDis(con1,con2),ConvexMinDis(con2,con1)));
        }
            
    }
    /*
    2.00000 322.91330 132.00758 229.96087 220.29299 285.24551 228.88643 265.17353 273.54159 
    278.82073 160.05624 283.06360 204.36487 234.82973 325.35826 2.00000 320.62439 130.09612 
    228.26520 217.84857 282.70479 228.35499 264.06817 271.83083 277.00181 157.19097 281.32543 
    202.27704 233.45235 323.73600 322.91330 320.62439 127.28162 48.15016 75.91705 7.00000 
    147.00000 147.13939 88.09830 18.00000 102.39141 75.00000 95.70789 86.02325 4.00000 132.00758 
    130.09612 127.28162 25.80698 24.36311 88.20431 56.32051 79.83107 69.40461 75.66373 25.15538 
    79.02531 5.77843 39.70142 121.43311 229.96087 228.26520 48.15016 25.80698 8.77678 25.67736 
    45.27693 65.36819 25.80603 12.00000 41.00000 29.18802 6.15651 7.42567 53.30219 220.29299 
    217.84857 75.91705 24.36311 8.77678 20.94556 124.19742 143.69016 91.78780 77.00000 19.00000 
    93.62149 31.39963 74.33034 112.09107 285.24551 282.70479 7.00000 88.20431 25.67736 20.94556 
    127.73801 134.73678 72.73239 20.00000 46.23851 62.76942 72.57472 65.19202 38.00000 228.88643 
    228.35499 147.00000 56.32051 45.27693 124.19742 127.73801 16.26346 41.71930 70.00714 159.76232 
    65.49046 64.40497 4.28413 92.35800 265.17353 264.06817 147.13939 79.83107 65.36819 143.69016 
    134.73678 16.26346 13.43503 75.27284 180.60177 67.91171 85.42248 6.27208 76.11833 273.54159 
    271.83083 88.09830 69.40461 25.80603 91.78780 72.73239 41.71930 13.43503 13.34166 134.25705 
    7.24416 51.47815 6.36396 7.00000 278.82073 277.00181 18.00000 75.66373 12.00000 77.00000 20.00000 
    70.00714 75.27284 13.34166 113.00000 7.96960 52.00000 16.68474 18.52915 160.05624 157.19097 
    102.39141 25.15538 41.00000 19.00000 46.23851 159.76232 180.60177 134.25705 113.00000 135.77085 
    68.39894 116.42048 137.87676 283.06360 281.32543 75.00000 79.02531 29.18802 93.62149 62.76942 
    65.49046 67.91171 7.24416 7.96960 135.77085 58.94065 18.91277 32.18925 204.36487 202.27704 95.70789 
    5.77843 6.15651 31.39963 72.57472 64.40497 85.42248 51.47815 52.00000 68.39894 58.94065 33.39838 
    103.12502 234.82973 233.45235 86.02325 39.70142 7.42567 74.33034 65.19202 4.28413 6.27208 6.36396 
    16.68474 116.42048 18.91277 33.39838 56.41515 325.35826 323.73600 4.00000 121.43311 53.30219 112.09107 
    38.00000 92.35800 76.11833 7.00000 18.52915 137.87676 32.18925 103.12502 56.41515 
    */

    数据生成

    #include <stdio.h>
    struct point{double x,y;};
    struct polygon
    {
        int n;
        point data[10];
    };
    #define N   16
    polygon p[N]={
        {4,{{0,0},{-1,0},{-1,-1},{0,-1}}},
        {4,{{2,0},{2,-1},{3,-1},{3,0}}},
        {4,{{247,208},{247,235},{375,235},{375,208}}},
        {3,{{85 ,101},{116 ,168},{168 ,103}}},
        {3,{{131 ,189},{216 ,148},{196 ,209}}},
        {3,{{180 ,127},{246 ,127},{202 ,144}}},
        {3,{{226 ,201},{297 ,201},{242 ,151}}},
        {3,{{42 ,225},{61 ,261},{100,222}}},
        {3,{{84 ,261},{99 ,246},{102,260}}},
        {3,{{72,309},{157,224},{167,309}}},
        {3,{{170,221},{229,221},{199,245}}},
        {3,{{190,90},{153,47},{225,108}}},
        {3,{{165,230},{168,242},{172,233}}},
        {6,{{143,146},{133,156},{138,170},{150,173},{161,166},{161,152}}},
        {5,{{109,208},{100,236},{111,253},{122,250},{161,206}}},
        {6,{{177,273},{174,309},{202,377},{417,375},{490,270},{268,239}}}
        };
    int main()
    {
        //freopen("C:\Documents and Settings\Administrator\桌面\out.txt","w",stdout);
        int i,j,k,num=0;
        for(i=0;i<N;i++)
        {
            for(j=0;j<N;j++)
            {
                if(i==j)
                    continue;
                num++;
                //if(num>35||num<=33)continue;
                printf("%d %d
    ",p[i].n,p[j].n);
                for(k=0;k<p[i].n;k++)
                    printf("%lf %lf
    ",p[i].data[k].x,p[i].data[k].y);
                for(k=0;k<p[j].n;k++)
                    printf("%lf %lf
    ",p[j].data[k].x,p[j].data[k].y);
                printf("
    
    ");
            }
        }
        printf("0 0
    ");
        return 0;
    }
  • 相关阅读:
    21.网络文件共享服务
    20.LANMP架构
    18.自动运维工具ansible
    17.MySQL数据库
    16.DNS服务
    15.系统自动部署
    14.加密技术和安全
    13.系统启动和服务管理
    12.进程管理和计划任务
    11.网络管理和配置
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12363694.html
Copyright © 2011-2022 走看看