BZOJ1857【SCOI2010】传送带 <三分法>

Problem

【SCOI2010】传送带

Time  Limit:  1  Sec\mathrm{Time\;Limit:\;1\;Sec}
Memory  Limit:  64  MB\mathrm{Memory\;Limit:\;64\;MB}

Description

在一个22维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段ABAB和线段CDCD
lxhgww\mathrm{lxhgww}ABAB上的移动速度为PP,在CDCD上的移动速度为QQ,在平面上的移动速度RR
现在lxhgww\mathrm{lxhgww}想从AA点走到DD点,他想知道最少需要走多长时间。

Input

输入数据第一行是44个整数,表示AABB的坐标,分别为Ax,Ay,Bx,ByA_x,A_y,B_x,B_y
第二行是44个整数,表示CCDD的坐标,分别为Cx,Cy,Dx,DyC_x,C_y,D_x,D_y
第三行是33个整数,分别是P,Q,RP,Q,R

Output

输出数据为一行,表示lxhgww\mathrm{lxhgww}AA点走到DD点的最短时间,保留到小数点后22位。

Sample Input

1
2
3
0 0 0 100
100 0 100 100
2 2 1

Sample Output

1
136.60

Hint

对于100%100\%的数据,1Ax,Ay,Bx,By,Cx,Cy,Dx,Dy1031\le A_x,A_y,B_x,B_y,C_x,C_y,D_x,D_y\le10^31P,Q,R101\le P,Q,R\le10

标签:三分法

Solution

三分套三分,据说有大学物理结论可以O(1)\mathrm{O(1)}做…
首先一定是从AA走到ABAB上的一点EE,然后走平面到CDCD上的一点FF,最后从FF沿CDCD走到DD
考虑确定ABAB上的EE点,那么若将FF点的所有位置都计算答案并画成函数图像,一定是一个单峰函数。那么确定EE后可以三分法找到最佳FF位置。
同样地,对于每个EE位置的最佳答案,也会呈一个单峰函数。因此可以先对EEABAB上进行三分,每次三分到的两个端点需要再对FFCDCD上进行三分找到最小时间。
这样一来,可以先在ABAB上三分EE,每次三分找端点最值的时候再在CDCD上三分FF,三分套三分即可找到答案。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <bits/stdc++.h>
#define EPS 1e-4
#define xx first
#define yy second
#define mp make_pair
#define pdd pair<dnt,dnt>
using namespace std;
typedef double dnt;
template <class T> inline void read(T &x) {
x = 0; int c = getchar(), f = 1;
for (; !isdigit(c); c = getchar()) if (c == 45) f = -1;
for (; isdigit(c); c = getchar()) (x *= 10) += f*(c-'0');
}
pdd A, B, C, D; dnt P, Q, R;
dnt sqr(dnt x) {return x*x;}
dnt dis(pdd x, pdd y) {return sqrt(sqr(x.xx-y.xx)+sqr(x.yy-y.yy));}
dnt tri_search_T(pdd l, pdd r, pdd S) {
dnt ret = dis(A, S)/dis(l, D)/Q+dis(S, l)/R; pdd llr, lrr;
while (fabs(l.xx-r.xx) > EPS || fabs(l.yy-r.yy) > EPS) {
llr = mp(l.xx+(r.xx-l.xx)/3, l.yy+(r.yy-l.yy)/3);
lrr = mp(r.xx-(r.xx-l.xx)/3, r.yy-(r.yy-l.yy)/3);
dnt tllr = dis(A, S)/P+dis(llr, D)/Q+dis(S, llr)/R;
dnt tlrr = dis(A, S)/P+dis(lrr, D)/Q+dis(S, lrr)/R;
if (tllr < tlrr) r = lrr; else l = llr;
ret = min(tllr, tlrr);
}
return ret;
}
dnt tri_search_S(pdd l, pdd r) {
dnt ret = tri_search_T(C, D, l); pdd llr, lrr;
while (fabs(l.xx-r.xx) > EPS || fabs(l.yy-r.yy) > EPS) {
llr = mp(l.xx+(r.xx-l.xx)/3, l.yy+(r.yy-l.yy)/3);
lrr = mp(r.xx-(r.xx-l.xx)/3, r.yy-(r.yy-l.yy)/3);
dnt tllr = tri_search_T(C, D, llr);
dnt tlrr = tri_search_T(C, D, lrr);
if (tllr < tlrr) r = lrr; else l = lrr;
ret = min(tllr, tlrr);
}
return ret;
}
int main() {
read(A.xx), read(A.yy), read(B.xx), read(B.yy);
read(C.xx), read(C.yy), read(D.xx), read(D.yy);
read(P), read(Q), read(R);
return printf("%.2lf\n", tri_search_S(A, B)), 0;
}