E - Line belt
In a two-dimensional plane there are two line belts, there are two segments AB and CD, lxhgww's speed on AB is P and on CD is Q, he can move with the speed R on other area on the plane.
How long must he take to travel from A to D?
Input
The first line is the case number T.
For each case, there are three lines.
The first line, four integers, the coordinates of A and B: Ax Ay Bx By.
The second line , four integers, the coordinates of C and D:Cx Cy Dx Dy.
The third line, three integers, P Q R.
0<= Ax,Ay,Bx,By,Cx,Cy,Dx,Dy<=1000
1<=P,Q,R<=10
Output
The minimum time to travel from A to D, round to two decimals.
Sample Input
1
0 0 0 100
100 0 100 100
2 2 1
Sample Output
136.60
显然,线段 AB 上一定存在一点 M , 线段 CD 上一定存在一点 N,使得总的行进时间最短。
为此,需要分别找出这两个点。由于对于给定的线段 AB 和线段 CD 都有确定的点 M、点 N 令总耗时最少,可以知道只要枚举出的 AB 上的点 P 偏离了 M, 或 CD 上的点 Q 偏离了 N,总耗时就会长于最短耗时。而当 P 越接近 M 时,对这个 P 而言耗时最短的 Q 也越接近 N。
于是,对线段 AB 进行三分查找,得到两个中间值,基于它们,对线段 CD 进行三分查找, 分别得到两个中间值的时间耗费,比较它们,继续对 AB 的三分查找,直到确定点 M 和点 N:
#include <iostream>
#include <cstdio>
#include <math.h>
#include <iomanip>
//#define TEST
#define PREC 1e-8
using namespace std;
struct point{
double x, y;
}a, b, c, d;
double P, Q, R;
double dist(point a, point b){
return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
}
double secondTS(point last){
point left = d, right = c, mid, midmid;
double t1, t2;
do{
mid.x = (left.x + right.x)/ 2, mid.y = (left.y + right.y) / 2;
midmid.x = (mid.x + right.x) / 2, midmid.y = (mid.y + right.y) / 2;
double d1 = dist(mid, last), d2 = dist(midmid, last);
double dM = dist(mid, d), dN = dist(midmid, d);
t1 = d1/R + dM/Q, t2 = d2/R + dN/Q;
if(t1 < t2)
right = midmid;
else
left = mid;
}while(dist(left, right) > PREC);
return t1;
}
double firstTS(){
point left = a, right = b, mid, midmid;
double t1, t2;
do{
mid.x = (left.x + right.x)/ 2, mid.y = (left.y + right.y) / 2;
midmid.x = (mid.x + right.x) / 2, midmid.y = (mid.y + right.y) / 2;
double d1 = dist(mid, a), d2 = dist(midmid, a);
t1 = d1 / P + secondTS(mid), t2 = d2 / P + secondTS(midmid);
if(t1 < t2)
right = midmid;
else
left = mid;
}while(dist(left, right) > PREC);
return t1;
}
int main(){
#ifdef TEST
freopen("test.txt", "r", stdin);
#endif // TEST
int T;
while(cin >> T){
for(int t = 0; t < T; t++){
cin >> a.x >> a.y >> b.x >> b.y >> c.x >> c.y >> d.x >> d.y >> P >> Q >> R;
double res = round(firstTS() * 100) / 100;
cout << fixed << setprecision(2) << res << endl;
}
}
return 0;
}