POJ 3608 Bridge Across Islands(模板小汇)

来源:互联网 发布:端口查询 编辑:程序博客网 时间:2024/06/05 12:34

求两个凸包间的最短距离。

大部分都是抄的小岛前辈的模板。

真是无私奉献的典范啊!应有尽有,巨细靡遗。。

顺便连带整理了一下自己的。(感觉自己的模板也写得变紧凑了。。)

#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <stdio.h>#include <math.h>using namespace std;#define MAXN 10010#define eps 1e-10//const double pi = acos(-1.0);inline double sig(double x) { return (x > eps) - (x < -eps); };template <class T> inline T sqr(T a) { return a * a; }struct Point{    double x, y;    Point() {}    Point(double _x, double _y): x(_x), y(_y) {}    void in();    void out() const;    double len() const;    double len2() const;    double dis(const Point &argu) const;    double dis2(const Point &argu) const;    bool operator <(const Point &argu) const;    Point operator -(const Point &argu) const;    double operator ^(const Point &argu) const;    double operator *(const Point &argu) const;};struct Segment{    Point a, b;    Segment() {}    Segment(Point _a, Point _b): a(_a), b(_b) {}    void in();    Point d() const;    void out() const;    double len() const;    double len2() const;    int sgn(const Segment &argu) const;    bool qrt(const Segment &argu) const;    double dis2(const Point &argu) const;    double dis2(const Segment &argu) const;};struct Line{    Segment l;    Line() {}    Line(Segment _l): l(_l) {}    double dis2(const Point &argu) const;    double dis2(const Segment &argu) const;};inline double Cross(const Point &o, const Point &a, const Point &b) { return (a - o) ^ (b - o); }void Point::in() { scanf("%lf%lf", &x, &y); }double Point::len() const { return sqrt(len2()); }double Point::len2() const { return x * x + y * y; }void Point::out() const{ printf("%.0lf %.0lf\n", x, y); }double Point::dis(const Point &argu) const { return sqrt(dis2(argu)); }double Point::operator ^(const Point &argu) const { return x * argu.y - y * argu.x; }double Point::operator *(const Point &argu) const { return x * argu.x + y * argu.y; }Point Point::operator -(const Point &argu) const { return Point(x - argu.x, y - argu.y); }bool Point::operator <(const Point &argu) const { return sig(x - argu.x) == 0 ? y < argu.y : x < argu.x; }double Point::dis2(const Point &argu) const { return (x - argu.x) * (x - argu.x) + (y - argu.y) * (y - argu.y); }void Segment::in() { a.in(), b.in(); }Point Segment::d() const { return b - a; }double Segment::len2() const { return d().len2(); }double Segment::len() const { return sqrt(len2()); }void Segment::out() const { a.out(), b.out(); }double Segment::dis2(const Segment &argu) const{    if(~sgn(argu)) return 0;    return min(min(dis2(argu.a), dis2(argu.b)), min(argu.dis2(a), argu.dis2(b)));}double Segment::dis2(const Point &argu) const{    Point pa = argu - a, pb = argu - b;    if(sig(d() * pa) <= 0) return pa.len2(); if(sig(d() * pb) >= 0) return pb.len2();    Line l = Line((*this)); return l.dis2(argu);}int Segment::sgn(const Segment &argu) const{    if(!qrt(argu)) return -1;    return sig(Cross(a, b, argu.a)) * sig(Cross(a, b, argu.b)) <= 0 &&           sig(Cross(argu.a, argu.b, a)) * sig(Cross(argu.a, argu.b, b)) <= 0 ? 1 : -1;}//快速排斥实验bool Segment::qrt(const Segment &argu) const{    return min(a.x, b.x) <= max(argu.a.x, argu.b.x) && min(a.y, b.y) <= max(argu.a.y, argu.b.y) &&           min(argu.a.x, argu.b.x) <= max(a.x, b.x) && min(argu.a.y, argu.b.y) <= max(a.y, b.y);}double Line::dis2(const Point &argu) const { return sqr(fabs(l.d() ^ (argu - l.a))) / l.len2(); }double Line::dis2(const Segment &argu) const{    Point v1 = argu.a - l.a, v2 = argu.b - l.b; double d1 = l.d() ^ v1, d2 = l.d() ^ v2;    return sig(d1) != sig(d2) ? 0 : sqr(min(fabs(d1), fabs(d2))) / l.len2();}int ConvexHull(Point p[], Point ch[], int n){    sort(p, p + n);    int top = 0;    for(int i = 0; i < n; i++)    {        while(top > 1 && Cross(ch[top - 2], ch[top - 1], p[i]) <= 0) top--;        ch[top++] = p[i];    }    int t = top;    for(int i = n - 2; i >= 0; i--)    {        while(top > t && Cross(ch[top - 2], ch[top - 1], p[i]) <= 0) top--;        ch[top++] = p[i];    }    top--;    return top;}double RotatingCalipers(Point p1[], int n1, Point p2[], int n2){    double ret = 1e15;    int t = 0, t1 = 1, t2 = 1;    for(int i = 0; i < n1; i++) if(p1[i].y > p1[t1].y) t1 = i;    for(int i = 0; i < n2; i++) if(p2[i].y < p2[t1].y) t1 = i;    for(int i = 0; i < n1; i++)    {        while(sig((p1[t1 + 1] - p1[t1]) ^ (p2[t2 + 1] - p2[t2])) > 0) t2 = (t2 + 1) % n2;        Segment s1 = Segment(p1[t1], p1[t1 + 1]);        Segment s2 = Segment(p2[t2], p2[t2 + 1]);        ret = min(ret, s1.dis2(s2));        t1 = (t1 + 1) % n1;    }    return ret;}Point p1[MAXN], ch1[MAXN];Point p2[MAXN], ch2[MAXN];int n1, n2, c1, c2;void solve(){    c1 = ConvexHull(p1, ch1, n1); ch1[c1] = ch1[0];    c2 = ConvexHull(p2, ch2, n2); ch2[c2] = ch2[0];    double d1 = RotatingCalipers(ch1, c1, ch2, c2);    double d2 = RotatingCalipers(ch2, c2, ch1, c1);    printf("%.5lf\n", sqrt(min(d1, d2)));}int main(){//    freopen("3608.in", "r", stdin);    while(scanf("%d%d", &n1, &n2) && (n1 || n2))    {        for(int i = 0; i < n1; i++) p1[i].in();        for(int i = 0; i < n2; i++) p2[i].in();        solve();    }    return 0;}


0 0
原创粉丝点击