博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

[poj][3608][Bridge Across Islands]

Posted on 2012-07-11 18:45  紫华弦筝  阅读(126)  评论(0编辑  收藏  举报

题目:http://poj.org/problem?id=3608

View Code
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>

#define clr(a,b) memset(a,b,sizeof(a))
#define sqr(x) ((x)*(x))
using namespace std;

const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const int N = 10000+10;

int dcmp(double x){
    if (x < -eps) return -1;
    else return x > eps;
}

struct cpoint
{
    double x, y;
    cpoint(){}
    cpoint(double x, double y):x(x), y(y){}
    void get() { scanf("%lf%lf", &x, &y); }
    bool operator == (const cpoint& u)const{
        return dcmp(x - u.x) == 0 && dcmp(y - u.y) == 0;
    }
};

double cross(cpoint o, cpoint p, cpoint q){
    return (p.x-o.x)*(q.y-o.y)-(q.x-o.x)*(p.y-o.y);
}
double dot(cpoint o, cpoint p, cpoint q){
    return (p.x-o.x)*(q.x-o.x)+(p.y-o.y)*(q.y-o.y);
}
double dis(cpoint p, cpoint q){
    return sqrt(sqr(p.x-q.x) + sqr(p.y-q.y));
}
double dissqr(cpoint p, cpoint q){
    return sqr(p.x-q.x) + sqr(p.y-q.y);
}
bool PointOnSegment(cpoint p0, cpoint p1, cpoint p2){
    return dcmp(cross(p0, p1, p2)) == 0 && dcmp(dot(p0, p1, p2)) <= 0;
}
double PointToLine(cpoint p0, cpoint p1, cpoint p2, cpoint &cp){
    double d = dis(p1, p2);
    double s = cross(p1, p2, p0) / d;
    cp.x = p0.x + s * (p2.y - p1.y) / d;
    cp.y = p0.y - s * (p2.x - p1.x) / d;
    return fabs(s);
}
cpoint bp;
int PolarCmp(const cpoint &p1, const cpoint &p2){
    int u = dcmp(cross(bp, p1, p2));
    return u > 0 || (u==0 && dcmp(dissqr(bp, p1)-dissqr(bp, p2))<0);
}
void graham(cpoint pin[], int n, cpoint ch[], int &m){
    int i, j, k, u, v;
    memcpy(ch, pin, n*sizeof(cpoint));
    for (i=k=0; i<n; i++){
        u = dcmp(ch[i].x - ch[k].x);
        v = dcmp(ch[i].y - ch[k].y);
        if (v < 0 || (v==0 && u<0)) k = i;
    }
    bp = ch[k];
    sort(ch, ch+n, PolarCmp);
    n = unique(ch, ch+n) - ch;
    if (n <= 1) { m = n; return ; }
    if (dcmp(cross(ch[0],ch[1],ch[n-1]))==0){
        m = 2; ch[1] = ch[n-1]; return ;
    }
    ch[n++] = ch[0];
    for (i=1, j=2; j<n; j++){
        while (i>0 && dcmp(cross(ch[i-1], ch[i], ch[j]))<=0)i--;
        ch[++i] = ch[j];
    }
    m = i;
}
double PointToSeg(cpoint p0, cpoint p1, cpoint p2){
    cpoint cp;
    double d = PointToLine(p0, p1, p2, cp);
    if (PointOnSegment(cp, p1, p2)) return d;
    else return min(dis(p0, p1), dis(p0, p2));
}
double DisPallSeg(cpoint p0, cpoint p1, cpoint p2, cpoint p3){
    return min(min(PointToSeg(p0, p2, p3), PointToSeg(p1, p2, p3)),
               min(PointToSeg(p2, p0, p1), PointToSeg(p3, p0, p1)));
}
void anticlockwise(cpoint cp[], int n){
    for (int i=0; i<n-2; i++){
        double t = cross(cp[i], cp[i+1], cp[i+2]);
        if (dcmp(t) > 0) return ;
        if (dcmp(t) < 0) { reverse(cp, cp+n); return ; }
    }
}
double rotating(cpoint ch1[], int n, cpoint ch2[], int m){
    int p = 0, q = 0;
    for (int i=0; i<n; i++)
        if (dcmp(ch1[i].y - ch1[p].y) < 0)
            p = i;
    for (int i=0; i<m; i++)
        if (dcmp(ch2[i].y - ch2[q]. y) > 0)
            q = i;
    ch1[n] = ch1[0], ch2[m] = ch2[0];
    double tmp, res = 1e99;
    for (int i=0; i<n; i++){
        while ((tmp = cross(ch1[p],ch1[p+1],ch2[q+1])-
            cross(ch1[p],ch1[p+1],ch2[q])) > eps)
            q = (q + 1) % m;
        if (dcmp(tmp) < 0) res = min(res, PointToSeg(ch2[q], ch1[p], ch1[p+1]));
        else res = min(res, DisPallSeg(ch1[p], ch1[p+1], ch2[q], ch2[q+1]));
        p = (p + 1) % m;
    }
    return res;
}

void solve(cpoint ch1[], int n, cpoint ch2[], int m){
    anticlockwise(ch1, n);
    anticlockwise(ch2, m);
    double ans = min(rotating(ch1, n, ch2, m), rotating(ch2, m, ch1, n));
    printf("%.5f\n", ans);
}
cpoint p[N], q[N];
int main()
{
    //freopen("D:/a.txt", "r", stdin);
    int n, m;
    while (~scanf("%d%d", &n, &m))
    {
        if (n==0 && m==0) break;
        for (int i=0; i<n; i++) p[i].get();
        for (int i=0; i<m; i++) q[i].get();
        solve(p, n, q, m);
    }
    return 0;
}