Problem
【SCOI2010】传送带
TimeLimit:1Sec
MemoryLimit:64MB
Description
在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。
lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。
现在lxhgww想从A点走到D点,他想知道最少需要走多长时间。
输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By。
第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy。
第三行是3个整数,分别是P,Q,R。
Output
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位。
1 2 3
| 0 0 0 100 100 0 100 100 2 2 1
|
Sample Output
Hint
对于100%的数据,1≤Ax,Ay,Bx,By,Cx,Cy,Dx,Dy≤103,1≤P,Q,R≤10。
标签:三分法
Solution
三分套三分,据说有大学物理结论可以O(1)做…
首先一定是从A走到AB上的一点E,然后走平面到CD上的一点F,最后从F沿CD走到D。
考虑确定AB上的E点,那么若将F点的所有位置都计算答案并画成函数图像,一定是一个单峰函数。那么确定E后可以三分法找到最佳F位置。
同样地,对于每个E位置的最佳答案,也会呈一个单峰函数。因此可以先对E在AB上进行三分,每次三分到的两个端点需要再对F在CD上进行三分找到最小时间。
这样一来,可以先在AB上三分E,每次三分找端点最值的时候再在CD上三分F,三分套三分即可找到答案。
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; }
|