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\n", 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\n");
173         return 0;
174     }
175     printf("%.5lf", Two());
176 }

 

posted @ 2017-05-12 16:55  草根柴鸡  阅读(230)  评论(0编辑  收藏  举报