zoukankan      html  css  js  c++  java
  • POJ 3608 Bridge Across Islands [旋转卡壳]

    Bridge Across Islands
    Time Limit: 1000MS   Memory Limit: 65536K
    Total Submissions: 10455   Accepted: 3093   Special Judge

    Description

    Thousands of thousands years ago there was a small kingdom located in the middle of the Pacific Ocean. The territory of the kingdom consists two separated islands. Due to the impact of the ocean current, the shapes of both the islands became convex polygons. The king of the kingdom wanted to establish a bridge to connect the two islands. To minimize the cost, the king asked you, the bishop, to find the minimal distance between the boundaries of the two islands. 

    Input

    The input consists of several test cases.
    Each test case begins with two integers NM. (3 ≤ NM ≤ 10000)
    Each of the next N lines contains a pair of coordinates, which describes the position of a vertex in one convex polygon.
    Each of the next M lines contains a pair of coordinates, which describes the position of a vertex in the other convex polygon.
    A line with N = M = 0 indicates the end of input.
    The coordinates are within the range [-10000, 10000].

    Output

    For each test case output the minimal distance. An error within 0.001 is acceptable.

    Sample Input

    4 4
    0.00000 0.00000
    0.00000 1.00000
    1.00000 1.00000
    1.00000 0.00000
    2.00000 0.00000
    2.00000 1.00000
    3.00000 1.00000
    3.00000 0.00000
    0 0

    Sample Output

    1.00000

    Source


    题意:给出两个凸多边形,求他们之间的最近距离

    经典:http://blog.csdn.net/acmaker/article/details/3178696
    
    
    用一个凸包的边去卡另一个凸包的点
    先找到一个凸包p的最低点和另一个凸包q的最高点,这样就有了两条线j,j+1和k,k+1来卡
    枚举j,移动k使得两条线差不多平行(用叉积判断;可以发现也是单调的)
    然后更新ans,如果平行就是平行线段之间最短距离,否则用点k和线段j,j+1的距离
     
    注意要用两次,因为分别用两个凸包去卡对方
     
    吐槽:哪里说要5位小数了!!!
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    typedef long long ll;
    const int N=5e4+5;
    const double INF=1e99;
    const double eps=1e-8;
    
    inline int sgn(double x){
        if(abs(x)<eps) return 0;
        else return x<0?-1:1;
    }
    
    struct Vector{
        double x,y;
        Vector(double a=0,double b=0):x(a),y(b){}
        bool operator <(const Vector &a)const{
            return sgn(x-a.x)<0||(sgn(x-a.x)==0&&sgn(y-a.y)<0);
        }
    };
    typedef Vector Point;
    Vector operator +(Vector a,Vector b){return Vector(a.x+b.x,a.y+b.y);}
    Vector operator -(Vector a,Vector b){return Vector(a.x-b.x,a.y-b.y);}
    Vector operator *(Vector a,double b){return Vector(a.x*b,a.y*b);}
    Vector operator /(Vector a,double b){return Vector(a.x/b,a.y/b);}
    bool operator ==(Vector a,Vector b){return sgn(a.x-b.x)==0&&sgn(a.y-b.y)==0;}
    double Dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
    double Cross(Vector a,Vector b){return a.x*b.y-a.y*b.x;}
    
    double Len(Vector a){return sqrt(Dot(a,a));}
    double Len2(Vector a){return Dot(a,a);}
    double DisTL(Point p,Point a,Point b){
        Vector v1=p-a,v2=b-a;
        return abs(Cross(v1,v2)/Len(v2));
    }
    double DisTS(Point p,Point a,Point b){
        if(a==b) return Len(p-a);
        Vector v1=p-a,v2=p-b,v3=b-a;
        if(sgn(Dot(v2,v3))>0) return Len(v2);
        else if(sgn(Dot(v1,v3))<0) return Len(v1);
        else return abs(Cross(v1,v3)/Len(v3));
    }
    
    int n,m;
    Point p[N],q[N];
    double RotatingCalipers(Point p[],int n,Point q[],int m){
        double ans=INF;
        p[n+1]=p[1];
        q[m+1]=q[1];
        int j=1,k=1,t;
        for(int i=1;i<=n;i++) if(p[i].y<p[j].y) j=i;
        for(int i=1;i<=m;i++) if(q[i].y>q[k].y) k=i;
        for(int i=1;i<=n;i++){
            while((t=sgn(Cross(p[j+1]-p[j],q[k]-q[k+1])))<0) k=k%m+1;
            if(t==0){
                ans=min(ans,min(DisTS(q[k],p[j],p[j+1]),DisTS(q[k+1],p[j],p[j+1])));
                ans=min(ans,min(DisTS(p[j],q[k],q[k+1]),DisTS(p[j+1],q[k],q[k+1])));
            }else ans=min(ans,DisTS(q[k],p[j],p[j+1]));
            j=j%n+1;
        }
        return ans;
    }
    
    int main(int argc, const char * argv[]) {
        while(true){
            scanf("%d%d",&n,&m);if(n==0&&m==0) break;
            for(int i=1;i<=n;i++) scanf("%lf%lf",&p[i].x,&p[i].y);
            for(int i=1;i<=m;i++) scanf("%lf%lf",&q[i].x,&q[i].y);
            double ans=min(RotatingCalipers(p,n,q,m),RotatingCalipers(q,m,p,n));
            printf("%.5f
    ",ans);
        }
    }
     
  • 相关阅读:
    bootstrap-select用法详解
    启动react项目报如下错误
    什么?女朋友生气哄不好?那是你没有这款神器!
    Python竟然能做这种进度条,看完别说WC!
    看完学习Python的萌新都在问的六个问题,你就可以毕业了!
    批量加水印防抄袭,Python轻松搞定!
    hdu_1272_小希的迷宫_201403091527
    hdu_1856_More is better_201403091720
    hdu_1213_How Many Tables_201403091126
    hdu_1232_畅通工程_201403091018
  • 原文地址:https://www.cnblogs.com/candy99/p/6358679.html
Copyright © 2011-2022 走看看