poj 3608 Bridge Across Islands(两凸包最近距离)

很裸的题,还是用旋转卡壳的方法。输入点的顺序就是逆时针输入了。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<vector>
#include<string>
#include<cstdio>
#include<bitset>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
#define FF(i, a, b) for(int i=a; i<b; i++)
#define FD(i, a, b) for(int i=a; i>=b; i--)
#define REP(i, n) for(int i=0; i<n; i++)
#define CLR(a, b) memset(a, b, sizeof(a))
#define PB push_back
#define LL long long
#define eps 1e-10
#define debug puts("**debug**")
using namespace std;

struct Point
{
    double x, y;
    Point(double x=0, double y=0):x(x), y(y){}
};
typedef Point Vector;

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 p) { return Vector(a.x*p, a.y*p); }
Vector operator / (Vector a, double p) { return Vector(a.x/p, a.y/p); }
bool operator < (const Point& a, const Point& b)
{
    return a.x < b.x || (a.x == b.x && a.y <b.y);
}
int dcmp(double x)
{
    if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1;
}
bool operator == (const Point& a, const Point& b)
{
    return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y) == 0;
}

double Dot(Vector a, Vector b) { return a.x*b.x + a.y*b.y; }
double Length(Vector a) { return sqrt(Dot(a, a)); }
double Cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x; }

//如果输入点是顺时针输入,转为逆时针顺序
void anticolockwise(Point *ch,int len)
{
    for(int i=0;i<len-2;i++)
    {
        double tmp = Cross(ch[i]-ch[i+2], ch[i+1]-ch[i+2]);
        if(tmp > eps)
            return;
        else if(tmp < -eps)
        {
            reverse(ch, ch+len);
            return;
        }
    }
}

//点p到直线ab的距离
double DistanceToSegment(Point p, Point a, Point b)
{
    if(a == b) return Length(p-a);
    Vector v1 = b-a, v2 = p-a, v3 = p-b;
    if(dcmp(Dot(v1, v2)) < 0) return Length(v2);
    else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);
    else return fabs(Cross(v1, v2)) / Length(v1);
}

double dis_pair_seg(Point p1, Point p2, Point p3, Point p4)
{
    return min(min(DistanceToSegment(p1, p3, p4), DistanceToSegment(p2, p3, p4)),
     min(DistanceToSegment(p3, p1, p2), DistanceToSegment(p4, p1, p2)));
}

double RC_Distance(Point *ch1, Point *ch2, int n, int m)
{
    int q=0, p=0;
    REP(i, n) if(ch1[i].y-ch1[p].y < -eps) p=i;
    REP(i, m) if(ch2[i].y-ch2[q].y > eps) q=i;
    ch1[n]=ch1[0];  ch2[m]=ch2[0];

    double tmp, ans=1e100;
    REP(i, n)
    {
        while((tmp = Cross(ch1[p+1]-ch1[p], ch2[q+1]-ch1[p]) - Cross(ch1[p+1]-ch1[p], ch2[q]- ch1[p])) > eps)
            q=(q+1)%m;
        if(tmp < -eps) ans = min(ans,DistanceToSegment(ch2[q],ch1[p],ch1[p+1]));
        else ans = min(ans,dis_pair_seg(ch1[p],ch1[p+1],ch2[q],ch2[q+1]));
        p=(p+1)%n;
    }
    return ans;
}

int n, m;
Point ch1[10001], ch2[10001];

int main()
{
    while(scanf("%d%d", &n, &m), n+m)
    {
        REP(i, n) scanf("%lf%lf", &ch1[i].x, &ch1[i].y);
        REP(i, m) scanf("%lf%lf", &ch2[i].x, &ch2[i].y);
        printf("%.5f\n", min(RC_Distance(ch1, ch2, n, m), RC_Distance(ch2, ch1, m, n)));
    }
    return 0;
}


你可能感兴趣的:(poj 3608 Bridge Across Islands(两凸包最近距离))