【bzoj1857】[Scoi2010]传送带 三分套三分
题目描述
在一个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
输出
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位
样例输入
0 0 0 100
100 0 100 100
2 2 1
样例输出
136.60
题解
三分套三分
显然路线是A->AB段上的某个点M->CD段上的某个点N->D。
容易发现,如果固定了点M,那么时间与N的位置的关系是一个单峰函数。并且在N为最优解的情况下,时间与M的位置的关系也是一个单峰函数。
于是三分套三分即可。三分M的位置,然后求最优解的过程中三分N的位置即可。
时间复杂度$O(cnt^2)$
#include <cmath> #include <cstdio> struct data { double x , y; data() {} data(double a , double b) {x = a , y = b;} data operator+(data a) {return data(x + a.x , y + a.y);} data operator*(int a) {return data(x * a , y * a);} data operator/(int a) {return data(x / a , y / a);} }A , B , C , D; double P , Q , R; inline double dis(data a , data b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } double solve(data M) { data l = C , r = D , mid1 , mid2; int cnt = 50; while(cnt -- ) { mid1 = (l * 2 + r) / 3 , mid2 = (l + r * 2) / 3; if(dis(M , mid1) / R + dis(mid1 , D) / Q < dis(M , mid2) / R + dis(mid2 , D) / Q) r = mid2; else l = mid1; } return dis(A , M) / P + dis(M , l) / R + dis(l , D) / Q; } int main() { scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf" , &A.x , &A.y , &B.x , &B.y , &C.x , &C.y , &D.x , &D.y , &P , &Q , &R); data l = A , r = B , mid1 , mid2; int cnt = 50; while(cnt -- ) { mid1 = (l * 2 + r) / 3 , mid2 = (l + r * 2) / 3; if(solve(mid1) < solve(mid2)) r = mid2; else l = mid1; } printf("%.2lf\n" , solve(l)); return 0; }