• hdu 4063 Aircraft(计算几何+最短路)


    不说了。。。说多了都是泪。。。从昨天下午一直wa到现在,直到刚刚才让人帮我找到所谓的“bug”,其实也算不上bug。。。

    这个题的思路就是:找出平面上的所有点:所有圆的交点以及所有圆的圆心。然后依次判断两点是否连通,连通的话两点距离便是其欧几里得距离。这样建完图之后直接跑s->t最短路就行了。。

    两点连通?也就是说这两点连成的线段,一直在圆内,任意圆都行。如何判断呢,求出该线段与所有圆的所有交点,排序后将其分段,依次判断每一段是否在任意圆内。这个么,在分段后,判断每一段的中点是否在圆内就行了。

    这题并不是很难啊?我的bug在哪??刚开始我是将所有圆的圆心都加到平面点集中,wa到死有木有。。。刚刚改了改,只加第一个跟最后一个圆的圆心。。立A。。为什么?

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<fstream>
    #include<sstream>
    #include<vector>
    #include<string>
    #include<cstdio>
    #include<bitset>
    #include<queue>
    #include<stack>
    #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 LL long long
    #define PB push_back
    #define eps 1e-10
    #define debug puts("**debug**")
    using namespace std;
    
    const double PI = acos(-1);
    const double INF = 1e20;
    const int maxn = 11111;
    struct Point
    {
        double x, y;
        Point (double x=0, double y=0):x(x), y(y) {}
    };
    typedef Point Vector;
    
    struct Circle
    {
       Point c;
       double r;
       Circle() {}
       Circle(Point c, double r) : c(c), r(r) {}
       Point point(double a) { return Point(c.x+cos(a)*r, c.y+sin(a)*r); }
    };
    
    struct Line
    {
        Point p;
        Vector v;
        double ang;
        Line(){}
        Line(Point p, Vector v) : p(p), v(v) {ang = atan2(v.y, v.x); }
        Point point(double t)
        {
            return Point(p.x + t*v.x, p.y + t*v.y);
        }
        bool operator < (const Line& L) const
        {
            return ang < L.ang;
        }
    };
    
    template <class T> T sqr(T x) { return x * x;}
    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); }
    bool operator >= (const Point& a, const Point& b) { return a.x >= b.x && a.y >= b.y; }
    bool operator <= (const Point& a, const Point& b) { return 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 Angel(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }
    double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }
    Vector vecunit(Vector x){ return x / Length(x);}
    Vector normal(Vector x) { return Point(-x.y, x.x) / Length(x);}
    double angel(Vector v) { return atan2(v.y, v.x); }
    
    bool OnSegment(Point p, Point a1, Point a2)
    {
        return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
    }
    bool InCircle(Point x, Circle c) { return dcmp(sqr(c.r) - sqr(Length(c.c - x))) > 0;}
    
    double DistanceToSeg(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);
        if(dcmp(Dot(v1, v3)) > 0) return Length(v3);
        return fabs(Cross(v1, v2)) / Length(v1);
    }
    
    void getLineABC(Point A, Point B, double& a, double& b, double& c)
    {
        a = A.y-B.y, b = B.x-A.x, c = A.x*B.y-A.y*B.x;
    }
    
    Point GetIntersection(Line a, Line b)
    {
        Vector u = a.p-b.p;
        double t = Cross(b.v, u) / Cross(a.v, b.v);
        return a.p + a.v*t;
    }
    
    int getCCintersection(Circle C1, Circle C2, vector<Point>& sol)
    {
        double d = Length(C1.c - C2.c);
        if(dcmp(d) == 0)
        {
            if(dcmp(C1.r - C2.r) == 0) return -1;
            return 0;
        }
        if(dcmp(C1.r + C2.r - d) < 0) return 0;
        if(dcmp(fabs(C1.r - C2.r) - d) > 0) return 0;
    
        double a = angel(C2.c - C1.c);
        double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2*C1.r*d));
    
        Point p1 = C1.point(a-da), p2 = C1.point(a+da);
        sol.PB(p1);
        if(p1 == p2) return 1;
        sol.PB(p2);
        return 2;
    }
    
    int getSegCircleIntersection(Line L, Circle C, Point* sol)
    {
        Vector nor = normal(L.v);
        Line pl = Line(C.c, nor);
        Point ip = GetIntersection(pl, L);
        double dis = Length(ip - C.c);
        if (dcmp(dis - C.r) > 0) return 0;
        Point dxy = vecunit(L.v) * sqrt(sqr(C.r) - sqr(dis));
        int ret = 0;
        sol[ret] = ip + dxy;
        if (OnSegment(sol[ret], L.p, L.point(1))) ret++;
        sol[ret] = ip - dxy;
        if (OnSegment(sol[ret], L.p, L.point(1))) ret++;
        return ret;
    }
    
    int T, n;
    vector<Point> sol;
    Circle C[30];
    Point s, t;
    bool vis[maxn];
    
    
    bool check(Point A, Point B)
    {
        vector<Point> gank;
        gank.PB(A);
        gank.PB(B);
        Point roshan[2];
        REP(i, n)
        {
            //线段ab与所有圆的交点
            int m = getSegCircleIntersection(Line(A, B-A), C[i], roshan);
            if(m == 1) gank.PB(roshan[0]);
            if(m == 2) gank.PB(roshan[0]), gank.PB(roshan[1]);
        }
    
        sort(gank.begin(), gank.end());
        int nc = gank.size();
    
        REP(i, nc-1)
        {
            Point mid = (gank[i] + gank[i+1]) / 2.0;
            //重点跳过
            if(mid == gank[i]) continue;
            bool flag = 0;
            REP(j, n) if(InCircle(mid, C[j]))//分段中点是否被任意圆覆盖
            {
                flag = 1;
                break;
            }
            if(!flag) return false;
        }
        return true;
    }
    
    struct Heap
    {
        double d; int u;
        bool operator < (const Heap& rhs) const
        {
            return dcmp(d-rhs.d) > 0;
        }
    };
    
    struct Edge
    {
        int from, to;
        double dist;
    };
    
    vector<Edge> edges;
    vector<int> G[maxn];
    bool done[maxn];
    double d[maxn];
    
    double dij(int s, int t, int n)
    {
        priority_queue<Heap> q; q.push((Heap){0.0, s});
        REP(i, n) d[i] = INF; d[s] = 0.0;
        CLR(done, 0);
        while(!q.empty())
        {
            Heap x = q.top(); q.pop();
            int u = x.u, nc = G[u].size();
            if(done[u]) continue;
            done[u] = 1;
            REP(i, nc)
            {
                Edge& e = edges[G[u][i]];
                if(dcmp(d[e.to]-d[u]-e.dist) > 0)
                {
                    d[e.to] = d[u] + e.dist;
                    q.push((Heap){d[e.to], e.to});
                }
            }
        }
        return d[t];
    }
    
    void add(int from, int to, double dist)
    {
        edges.PB((Edge){from, to, dist});
        edges.PB((Edge){to, from, dist});
        int nc = edges.size();
        G[from].PB(nc-2);
        G[to].PB(nc-1);
    }
    
    void init()
    {
        REP(i, maxn) G[i].clear();
        sol.clear();
        edges.clear();
    }
    
    int main()
    {
        scanf("%d", &T);
        FF(kase, 1, T+1)
        {
            init();
            scanf("%d", &n);
            //sol存平面上所有点
            REP(i, n)
            {
                scanf("%lf%lf%lf", &C[i].c.x, &C[i].c.y, &C[i].r);
                if(i == 0 || i == n-1)
                    sol.PB(C[i].c);//加入圆心....
            }
            REP(i, n) FF(j, i+1, n)
                getCCintersection(C[i], C[j], sol);//所有圆的交点
    
            //去重
            sort(sol.begin(), sol.end());
            int nc = unique(sol.begin(), sol.end()) - sol.begin();
    
            int s, t;
            REP(i, nc)
            {
                FF(j, i+1, nc) if(check(sol[i], sol[j]))
                //判断两点是否连通
                    add(i, j, Length(sol[i] - sol[j]));
                //最短路的起始点
                if(sol[i] == C[0].c) s = i;
                if(sol[i] == C[n-1].c) t = i;
            }
    
            double ans = dij(s, t, nc);
            printf("Case %d: ", kase);
            if(dcmp(ans-INF) >= 0) puts("No such path.");
            else printf("%.4lf
    ", ans);
        }
        return 0;
    }
    



  • 相关阅读:
    内存溢出与内存泄漏
    Android性能优化系列之Bitmap图片优化
    android 内存泄漏,以及检测方法
    android view绘制流程 面试
    USACO milking cows
    USACO beads
    POJ3311 TSP问题 xingxing在努力
    HDU5074 dp xingxing在努力
    HDU2821 深搜 xingxing1024
    HDU5592 排队问题 xingxing在努力
  • 原文地址:https://www.cnblogs.com/pangblog/p/3320122.html
Copyright © 2020-2023  润新知