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);
        }
    }
     
  • 相关阅读:
    J2EE中常用的名词解释
    java中的构造方法
    String s = new String("xyz");创建了几个StringObject?
    MySQL 学习笔记
    《SQL 必知必会》建表语句
    《SQL 必知必会》读书笔记
    IDEA 中项目代码修改后不自动生效,需要执行 mvn clean install 才生效
    curl 使用指南
    MySQL字段添加注释,但不改变字段的类型
    《痞子衡嵌入式半月刊》 第 14 期
  • 原文地址:https://www.cnblogs.com/candy99/p/6358679.html
Copyright © 2011-2022 走看看