zoukankan      html  css  js  c++  java
  • BZOJ 4077 Messenger

    Messenger

    【问题描述】

    alice和bob各自在两条折线上行进,一个邮递员要从alice那拿一个包裹,并以直线移动到bob处,alice和bob、邮递员的速度均为1单位/s,问邮递员最少要走多少秒才能送完包裹。

    【输入格式】

    输入数据的第一行是一个整数na,代表alice运动轨迹的折线上的顶点数。
    之后na行,每行两个整数,依次代表这个折线的第1号点、第2号点......第na号点的坐标。
    之后一行是一个整数nb,代表bob运动轨迹的折线上的顶点数。
    之后nb行,每行两个整数,依次代表这个折线的第1号点、第2号点......第nb号点的坐标。
    na,nb目测是50000以内

    【输出格式】

     输出只有一行,一个小数,代表邮递员最少要走的时间。若无解,输出impossible

    【样例输入】

    2
    0 0
    0 10
    2
    4 10
    4 0

    【样例输出】

    4.00000


    题解:

    考虑二分答案

    让 Bob 提前走 mid,那么 Alice 与 Bob 的实时距离就是 快递员要走的时间

    Check时不断移动,移动的距离是两个人分别与下一个点的距离中的较小值

    问题变成了求实时距离(两个人有速度,在不同线段上运动)的最小值

    我们以 Alice 为参考系,Bob 匀速移动,并且距离是不变的

    就变成了求点(Allice所在位置)到直线(Bob的移动轨迹)的距离、

    那么用点积判断是否组成锐角三角形,是的话用叉积求投影,否则就是点与直线两端点的较小值

    无解的话 Check( Bob 的总路程) 一下就可以了

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstdlib>
      4 #include<cstring>
      5 #include<iostream>
      6 #include<algorithm>
      7 using namespace std;
      8 inline void Scan(int &x)
      9 {
     10     char c;
     11     bool o = false;
     12     while(!isdigit(c = getchar())) o = (c != '-') ? o : true;
     13     x = c - '0';
     14     while(isdigit(c = getchar())) x = x * 10 + c - '0';
     15     if(o) x = -x;
     16 }
     17 const int maxn = 1e5;
     18 const double inf = 2e10;
     19 const double eps = 1e-8;
     20 struct point
     21 {
     22     double x, y;
     23     friend inline point operator + (point a, point b)
     24     {
     25         return (point) {a.x + b.x, a.y + b.y};
     26     }
     27     friend inline point operator - (point a, point b)
     28     {
     29         return (point) {a.x - b.x, a.y - b.y};
     30     }
     31     friend inline point operator * (point a, double x)
     32     {
     33         return (point) {a.x * x, a.y * x};
     34     }
     35     friend inline point operator / (point a, double x)
     36     {
     37         return (point) {a.x / x, a.y / x};
     38     }
     39     friend inline double operator * (point a, point b)
     40     {
     41         return a.x * b.y - a.y * b.x;
     42     }
     43     friend inline double operator ^ (point a, point b)
     44     {
     45         return a.x * b.x + a.y * b.y;
     46     }
     47     inline void print()
     48     {
     49         printf("x=%.2lf y=%.2lf
    ", x, y);
     50     }
     51 };
     52 struct ele
     53 {
     54     int n;
     55     double t;
     56     point p;
     57     void print()
     58     {
     59         printf("n=%d t=%.2lf ", n, t);
     60         p.print();
     61     }
     62 };
     63 inline double Sqr(double x)
     64 {
     65     return x * x;
     66 }
     67 inline double Dis(point a, point b)
     68 {
     69     return sqrt(Sqr(a.x - b.x) + Sqr(a.y - b.y));
     70 }
     71 inline int Sgn(double x)
     72 {
     73     if(x < -eps) return -1;
     74     if(x > eps) return 1;
     75     return 0;
     76 }
     77 inline double Dis(point a, point b, point c)
     78 {
     79     if(Sgn(Dis(b, c)))
     80         if(Sgn((a - b) ^ (c - b)) >= 0 && Sgn((a - c) ^ (b - c)) >= 0)
     81             return fabs(((a - b) * (c - b)) / Dis(b, c));
     82     return min(Dis(a, b), Dis(a, c));
     83 }
     84 struct thing
     85 {
     86     int n;
     87     point p[maxn];
     88     double s[maxn];
     89     inline void Read()
     90     {
     91         Scan(n);
     92         for(int i = 1; i <= n; ++i)
     93         {
     94             scanf("%lf%lf", &p[i].x, &p[i].y);
     95             if(i > 1) s[i] = s[i - 1] + Dis(p[i], p[i - 1]);
     96         }
     97     }
     98 };
     99 thing a, b;
    100 inline point Pos(bool o, double x, int p)
    101 {
    102     if(o) return b.p[p] + (b.p[p + 1] - b.p[p]) * (x / (b.s[p + 1] - b.s[p]));
    103     return a.p[p] + (a.p[p + 1] - a.p[p]) * (x / (a.s[p + 1] - a.s[p]));
    104 }
    105 point va, vb, dv;
    106 inline double Mini(point a, point b, point c, point d, double dis)
    107 {
    108     va = (b - a) / Dis(a, b);
    109     vb = (d - c) / Dis(c, d);
    110     dv = vb - va;
    111     d = c + dv * dis;
    112     return Dis(a, c, d);
    113 }
    114 inline bool Check(double mid)
    115 {
    116     ele u, v;
    117     u = (ele) {1, 0, a.p[1]};
    118     int n = upper_bound(b.s + 1, b.s + 1 + b.n, mid) - b.s - 1;
    119     double s = mid - b.s[n];
    120     v = (ele) {n, s, Pos(true, s, n)};
    121     int x, y;
    122     double l, r, res;
    123     while(true)
    124     {
    125         if(Dis(u.p, v.p) < mid + eps) return true;
    126         if(u.n == a.n || v.n == b.n) break;
    127         x = u.n + 1, y = v.n + 1;
    128         l = Dis(u.p, a.p[x]), r = Dis(v.p, b.p[y]);
    129         res = Mini(u.p, a.p[x], v.p, b.p[y], min(l, r));
    130         if(res < mid + eps) return true;
    131         if(!Sgn(l - r))
    132         {
    133             u = (ele) {x, 0, a.p[x]};
    134             v = (ele) {y, 0, b.p[y]};
    135             continue;
    136         }
    137         if(l < r)
    138         {
    139             u = (ele) {x, 0, a.p[x]};
    140             v.t += l;
    141             v.p = Pos(true, v.t, v.n);
    142         }
    143         else
    144         {
    145             u.t += r;
    146             u.p = Pos(false, u.t, u.n);
    147             v = (ele) {y, 0, b.p[y]};
    148         }
    149     }
    150     return false;
    151 }
    152 inline double Two()
    153 {
    154     int num = 50;
    155     double mi;
    156     double l = 0, r = b.s[b.n];
    157     while(num--)
    158     {
    159         mi = (l + r) / 2.0;
    160         if(Check(mi)) r = mi;
    161         else l = mi;
    162     }
    163     if(Check(l)) return l;
    164     return r;
    165 }
    166 int main()
    167 {
    168     a.Read();
    169     b.Read();
    170     if(!(Check(b.s[b.n])))
    171     {
    172         printf("impossible
    ");
    173         return 0;
    174     }
    175     printf("%.5lf", Two());
    176 }
  • 相关阅读:
    函数
    字符串格式化
    集合
    习题02
    int/str/list/tuple/dict必会
    元组/字典
    列表方法
    练习题(format、expandtabs、片层)
    字符串方法
    JMM
  • 原文地址:https://www.cnblogs.com/lytccc/p/6846282.html
Copyright © 2011-2022 走看看