• hdu 4063 Aircraft (Geometry + SP)


    Problem - 4063

      几何加简单最短路。

      题意是给出若干圆的圆心以及半径,求出从给出的起点到终点的最短路径的长度,可以移动的区域是圆覆盖到的任意一个位置。

      做法是这样的,对圆两两求交点,用这些得到的交点以及起点和终点作为我们要构造的图的顶点。因为我们要的是最短路径,所以如果我们要从一个区域穿越到另一区域的时候,必然是经过这些交点的。然后我们可以对这些交点两两判断是否能够相互到达。这个判断才是这道题的关键。判断的方法可以有几种,我想到的一是先求出直线与所有圆的交点,排序以后判断所有的圆能否覆盖掉这条线段;而我的是另一种方法,就是用一个队列,将还没有被覆盖的线段存在队列里,每次跟圆相交判断线段是否仍未被覆盖。

      最后来一个单源最短路就搞掂了!

    代码如下:

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 #include <cmath>
      6 #include <vector>
      7 #include <queue>
      8 
      9 using namespace std;
     10 
     11 const double EPS = 1e-10;
     12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);}
     13 struct Point {
     14     double x, y;
     15     Point() {}
     16     Point(double x, double y) : x(x), y(y) {}
     17     bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;}
     18     bool operator <= (Point a) const { return (sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && sgn(y - a.y) < 0) || (sgn(x - a.x) == 0 && sgn(y - a.y) == 0);}
     19     bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;}
     20     void print() { cout << x << '~' << y << endl;}
     21 } ;
     22 template <class T> T sqr(T x) { return x * x;}
     23 typedef Point Vec;
     24 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);}
     25 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);}
     26 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);}
     27 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);}
     28 
     29 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;}
     30 inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);}
     31 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;}
     32 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);}
     33 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));}
     34 inline double angle(Vec v) { return atan2(v.y, v.x);}
     35 inline double angle(Vec a, Vec b) { return acos(dotDet(a, b) / vecLen(a) / vecLen(b));}
     36 inline Vec vecUnit(Vec x) { return x / vecLen(x);}
     37 inline Vec rotate(Vec x, double rad) { return Vec(x.x * cos(rad) - x.y * sin(rad), x.x * sin(rad) + x.y * cos(rad));}
     38 inline Vec normal(Vec x) { return Vec(-x.y, x.x) / vecLen(x);}
     39 
     40 struct Line {
     41     Point s, t;
     42     Line() {}
     43     Line(Point s, Point t) : s(s), t(t) {}
     44     Vec vec() { return t - s;}
     45     Point point(double x) { return s + vec() * x;}
     46 } ;
     47 typedef Line Seg;
     48 
     49 inline bool onSeg(Point x, Point a, Point b) { return sgn(crossDet(a - x, b - x)) == 0 && sgn(dotDet(a - x, b - x)) < 0;}
     50 inline bool onSeg(Point x, Seg s) { return onSeg(x, s.s, s.t);}
     51 
     52 inline Point lineIntersect(Point P, Vec v, Point Q, Vec w) { return P + v * (crossDet(w, P - Q) / crossDet(v, w));}
     53 inline Point lineIntersect(Line a, Line b) { return lineIntersect(a.s, a.vec(), b.s, b.vec());}
     54 
     55 struct Circle {
     56     Point c;
     57     double r;
     58     Circle() {}
     59     Circle(Point c, double r) : c(c), r(r) {}
     60     Point point(double a) { return Point(c.x + cos(a) * r, c.y + sin(a) * r);}
     61 } ;
     62 int lineCircleIntersect(Line L, Circle C, vector<Point> &sol) {
     63     Vec nor = normal(L.vec());
     64     Point mid = lineIntersect(C.c, nor, L.s, L.vec());
     65     double len = sqr(C.r) - sqr(vecLen(C.c - mid));
     66     if (sgn(len) < 0) return 0;
     67     if (sgn(len) == 0) { sol.push_back(mid); return 1;}
     68     Vec dis = vecUnit(L.vec());
     69     len = sqrt(len);
     70     sol.push_back(mid + dis * len);
     71     sol.push_back(mid - dis * len);
     72     return 2;
     73 }
     74 
     75 int circleCircleIntersect(Circle C1, Circle C2, vector<Point> &sol) {
     76     double d = vecLen(C1.c - C2.c);
     77     if (sgn(d) == 0) {
     78         if (sgn(C1.r - C2.r) == 0) return -1;
     79         return -3 + (C1.r > C2.r);
     80     }
     81     if (sgn(C1.r + C2.r - d) < 0) return 0;
     82     if (sgn(fabs(C1.r - C2.r) - d) > 0) return -3 + (C1.r > C2.r);
     83     double a = angle(C2.c - C1.c);
     84     double da = acos((sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2.0 * C1.r * d));
     85     Point p1 = C1.point(a - da), p2 = C1.point(a + da);
     86     sol.push_back(p1);
     87 //    p1.print();
     88     if (p1 == p2) return 1;
     89     sol.push_back(p2);
     90 //    p2.print();
     91     return 2;
     92 }
     93 
     94 inline bool ptInCircle(Point p, Circle c) { return sgn(vecLen(c.c - p) - c.r) <= 0;}
     95 
     96 const int N = 33;
     97 Circle dev[N];
     98 vector<Point> vex;
     99 int sid, tid;
    100 double mat[N * N][N * N];
    101 
    102 Seg qseg[N * N];
    103 
    104 double cal(int pi, int pj, int n) {
    105 //    queue<Seg> seg;
    106     vector<Point> ip;
    107     int qh, qt;
    108     qh = qt = 0;
    109 //    while (!seg.empty()) seg.pop();
    110     if (vex[pj] < vex[pi]) swap(pi, pj);
    111     Seg L = Seg(vex[pi], vex[pj]);
    112 //    seg.push(L);
    113     qseg[qt++] = L;
    114     for (int i = 0; i < n; i++) {
    115 //        int sz = seg.size();
    116         int sz = qt - qh;
    117         for (int j = 0; j < sz; j++) {
    118 //            Seg tmp = seg.front();
    119 //            seg.pop();
    120             Seg tmp = qseg[qh++];
    121 //            if (pi == 0 && pj == 2) {
    122 //                tmp.s.print();
    123 //                tmp.t.print();
    124 //                puts("tmp");
    125 //            }
    126             ip.clear();
    127             if (lineCircleIntersect(L, dev[i], ip) == 2) {
    128                 if (ip[1] < ip[0]) swap(ip[0], ip[1]);
    129 //                if (pi == 0 && pj == 4) {
    130 //                    ip[0].print();
    131 //                    ip[1].print();
    132 //                    puts("ip");
    133 //                }
    134                 if (ip[1] <= tmp.s || tmp.t <= ip[0])
    135 //                    seg.push(tmp);
    136                     qseg[qt++] = tmp;
    137                 else if (tmp.s <= ip[0] && ip[1] <= tmp.t) {
    138                     if (vecLen(tmp.s - ip[0]) > EPS)
    139 //                        seg.push(Seg(tmp.s, ip[0]));
    140                         qseg[qt++] = Seg(tmp.s, ip[0]);
    141                     if (vecLen(tmp.t - ip[1]) > EPS)
    142 //                        seg.push(Seg(ip[1], tmp.t));
    143                         qseg[qt++] = Seg(ip[1], tmp.t);
    144                 } else if (tmp.s < ip[0] && ip[0] <= tmp.t && sgn(vecLen(tmp.s - ip[0])))
    145 //                    seg.push(Seg(tmp.s, ip[0]));
    146                     qseg[qt++] = Seg(tmp.s, ip[0]);
    147                 else if (tmp.s <= ip[1] && ip[1] < tmp.t && sgn(vecLen(ip[1] - tmp.t)))
    148 //                    seg.push(Seg(ip[1], tmp.t));
    149                     qseg[qt++] = Seg(ip[1], tmp.t);
    150             } else
    151 //                seg.push(tmp);
    152                 qseg[qt++] = tmp;
    153         }
    154 //        if (seg.size() == 0)
    155         if (qh == qt)
    156             return vecLen(vex[pi] - vex[pj]);
    157     }
    158     return -1.0;
    159 }
    160 
    161 void PRE(int n) {
    162     vex.clear();
    163     for (int i = 0; i < n; i++) {
    164         cin >> dev[i].c.x >> dev[i].c.y >> dev[i].r;
    165 //        vex.push_back(dev[i].c);
    166     }
    167     vex.push_back(dev[0].c);
    168     vex.push_back(dev[n - 1].c);
    169     Point ps = dev[0].c, pt = dev[n - 1].c;
    170     for (int i = 0; i < n; i++) {
    171         for (int j = 0; j < i; j++) {
    172 //            cout << i << " = = " << j << endl;
    173             circleCircleIntersect(dev[i], dev[j], vex);
    174         }
    175     }
    176     sort(vex.begin(), vex.end());
    177     int t = (int) (unique(vex.begin(), vex.end()) - vex.begin());
    178     while (vex.size() > t) vex.pop_back();
    179 //    cout << "size " << vex.size() << endl;
    180     for (int i = 0, sz = vex.size(); i < sz; i++) {
    181         if (vex[i] == ps) sid = i;
    182         if (vex[i] == pt) tid = i;
    183         for (int j = 0; j <= i; j++) {
    184             if (i == j) mat[i][j] = 0.0;
    185             else mat[i][j] = mat[j][i] = cal(i, j, n);
    186         }
    187     }
    188 //    cout << sid << ' ' << tid << endl;
    189 //    for (int i = 0, sz = vex.size(); i < sz; i++) {
    190 //        vex[i].print();
    191 //        for (int j = 0; j < sz; j++) printf("%7.4f ", mat[i][j]);
    192 //        cout << endl;
    193 //    }
    194 }
    195 
    196 const double FINF = 1e100;
    197 double dis[N * N];
    198 int q[N * N << 1];
    199 double spfa() {
    200     int sz = vex.size();
    201 //    queue<int> Q;
    202 //    while (!Q.empty()) Q.pop();
    203     int qh, qt;
    204     qh = qt = 0;
    205     for (int i = 0; i < sz; i++) dis[i] = FINF;
    206     dis[sid] = 0.0;
    207 //    Q.push(sid);
    208     q[qt++] = sid;
    209 //    while (!Q.empty()) {
    210     while (qh < qt) {
    211 //        int cur = Q.front();
    212 //        Q.pop();
    213         int cur = q[qh++];
    214         for (int i = 0; i < sz; i++) {
    215             if (mat[cur][i] < 0) continue;
    216             if (dis[i] > dis[cur] + mat[cur][i]) {
    217                 dis[i] = dis[cur] + mat[cur][i];
    218 //                Q.push(i);
    219                 q[qt++] = i;
    220             }
    221         }
    222     }
    223 //    for (int i = 0; i < sz; i++) cout << dis[i] << ' '; cout << endl;
    224     return dis[tid];
    225 }
    226 
    227 int main() {
    228 //    freopen("in", "r", stdin);
    229 //    freopen("out", "w", stdout);
    230     int T, n;
    231     cin >> T;
    232     for (int cas = 1; cas <= T; cas++) {
    233         cin >> n;
    234         PRE(n);
    235         printf("Case %d: ", cas);
    236         double ans = spfa();
    237         if (ans < FINF) printf("%.4f
    ", ans);
    238         else puts("No such path.");
    239     }
    240     return 0;
    241 }
    View Code

    附加自己出的数据:

     1 8
     2 2
     3 0 0 1
     4 2 0 1
     5 2
     6 0 0 1
     7 4 1 2
     8 3
     9 -3 0 2
    10 0 2 2
    11 3 0 2
    12 3
    13 -3 0 2
    14 0 3 3
    15 3 0 2
    16 6
    17 -6 0 2
    18 -3 0 2
    19 0 3 3
    20 3 0 2
    21 7 0 2
    22 0 8 2
    23 10
    24 -6 0 2
    25 -3 0 2
    26 0 3 3
    27 3 0 2
    28 7 0 2
    29 0 8 2
    30 -4 8 2
    31 -8 8 2
    32 -7 2 2
    33 -8 4 2
    34 3
    35 0 10 7
    36 -1 -1 100
    37 10 0 7
    38 3
    39 -3 0 2
    40 0 3 3
    41 3 0 2
    View Code

    ——written by Lyon

  • 相关阅读:
    springboot之异步调用@Async
    springboot之约定大约配置
    springboot之定时任务@Scheduled
    百度地图API
    JS触发服务器控件的单击事件
    jquery复选框 选中事件 及其判断是否被选中
    NopCommerce源码架构详解--初识高性能的开源商城系统cms
    基于dapper的通用泛型分页
    基于JQuery 的消息提示框效果代码
    kindeditor支持flv视频播放方法
  • 原文地址:https://www.cnblogs.com/LyonLys/p/hdu_4063_Lyon.html
Copyright © 2020-2023  润新知