Problem Description
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
思路:
首先,时间最短的路径必定是至多3条直线段构成的,一条在AB上,一条在CD上,一条架在两条线段之间。其次,如果有一个固定的点,求到另外一条线段上的一个端点上的最短距离,怎么做呢,可以通过三分来解,应该可以想到,枚举线段上的两个端点作为左右两个端点。这样线段上每个点作为中间点的距离从固定点到线段上的端点的距离就构成了一个凹形函数,这样子就可以用三分枚举出最小值。接着我们就用三分枚举AB上的那个最小值点,通过确定的那个点,在CD上三分出最小值。这样子通过三分嵌套三分的算法。就可以确定出答案了。
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 10010
#define ll long long
#define MIN 1e-9
#define eps 1e-7
#define pi acos(-1)
using namespace std;
struct Point
{
double x, y;
}a, b, c, d, aa, dd;
double ab, cd;
double p, q, r;
double dist(Point u, Point v)
{
return sqrt(eps+(u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y));
}
double fun(double t)
{
dd.x = d.x + (c.x-d.x)/cd*t*q;
dd.y = d.y + (c.y-d.y)/cd*t*q;
return t+dist(aa, dd)/r;
}
double sanfen(double t)
{
aa.x = a.x + (b.x-a.x)/ab*t*p;
aa.y = a.y + (b.y-a.y)/ab*t*p;
double low = 0, high = cd/q, mid, mmid;
while(high-low > eps)
{
mid = (high+low)/2;
mmid = (high+mid)/2;
if (fun(mid) < fun(mmid)) high = mmid+MIN;
else low = mid+MIN;
}
return t+fun(mid);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int T;
double low, high, mid, mmid;
cin >> T;
while(T--)
{
cin >> a.x >> a.y >> b.x >> b.y;
cin >> c.x >> c.y >> d.x >> d.y;
cin >> p >> q >> r;
ab = dist(a, b);
cd = dist(c, d);
low = 0;
high = ab/p;
while(high-low > eps)
{
mid = (low+high)/2;
mmid = (mid+high)/2;
if (sanfen(mid) < sanfen(mmid)) high = mmid+MIN;
else low = mid+MIN;
}
cout.setf(ios::fixed);
cout << setprecision(2) << sanfen(mid) << endl;
}
return 0;
}