1857: [Scoi2010]传送带
Time Limit: 1 Sec Memory Limit: 64 MB Submit: 1786 Solved: 981 [Submit][Status][Discuss]Description
在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间
Input
输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By 第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy 第三行是3个整数,分别是P,Q,R
Output
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位
Sample Input
0 0 0 100
100 0 100 100
2 2 1
100 0 100 100
2 2 1
Sample Output
136.60
HINT
对于100%的数据,1<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000 1<=P,Q,R<=10
路径显然是先在第一条线段上走一段,然后在平面上走一段,再到第二条线段上走一段
根据生活经验
如果把点的位置看作自变量,距离看作函数值,那么肯定有一点最优然后两边单调地变劣
所以可以在第一根线段上三分,然后求最短距离则需要在第二根线段上三分
#include <cmath> #include <cstdio> #include <iostream> using namespace std; double xl1, yl1, xr1, yr1, xl2, yl2, xr2, yr2, len1, len2, xx, yy, p, q, r; inline double sqr(const double &x){ return x * x; } inline double dis(const double &x1, const double &y1, const double &x2, const double &y2){ return sqr(x1 - x2) + sqr(y1 - y2); } inline double calc2(const double &lam){ double xt = xl2 + lam * (xr2 - xl2), yt = yl2 + lam * (yr2 - yl2); return sqrt(dis(xx, yy, xt, yt)) / r + len2 * (1 - lam) / q; } inline double calc(const double &lam){ xx = xl1 + lam * (xr1 - xl1), yy = yl1 + lam * (yr1 - yl1); double l = 0, r = 1, m1, m2, t1, t2; while(r - l > 0.00001){ m1 = (r + 2 * l) / 3; m2 = (2 * r + l) / 3; t1 = calc2(m1); t2 = calc2(m2); if(t1 > t2) l = m1; else r = m2; } return len1 * lam / p + min(t1, t2); } int main(){ cin >> xl1 >> yl1 >> xr1 >> yr1 >> xl2 >> yl2 >> xr2 >> yr2 >> p >> q >> r; len1 = sqrt(dis(xl1, yl1, xr1, yr1)); len2 = sqrt(dis(xl2, yl2, xr2, yr2)); double l = 0, r = 1, m1, m2, t1, t2; while(r - l > 0.00001){ m1 = (r + 2 * l) / 3; m2 = (2 * r + l) / 3; t1 = calc(m1); t2 = calc(m2); if(t1 > t2) l = m1; else r = m2; } printf("%.2lf", min(t1, t2)); return 0; }