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.<br>How long must he take to travel from A to D?
Input
The first line is the case number T.<br>For each case, there are three lines.<br>The first line, four integers, the coordinates of A and B: Ax Ay Bx By.<br>The second line , four integers, the coordinates of C and D:Cx Cy Dx Dy.<br>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
10 0 0 100100 0 100 1002 2 1
Sample Output
136.60
题目链接:点击打开链接
题意:(我看的别人的,蒟蒻的我不会翻译)
有两条传送带,传送带上有两段,AB和CD,它们的速度分别是P和Q,其它地方的速度为R,问从A到D所需要的最短时间是多少,此问题的一般过程如下图:
思路:
试想如果求AB上固定一点X到CD的距离,那么这样的函数关系一定是一个凹函数,因为一定有一个最短距离,然后向CD两端延伸距离都是越来越大的。所以,求解凹函数的极值问题,三分法首当其冲,先使用三分枚举AB段上的最优解,针对枚举的每一个值,再使用三分法枚举CD段上的最优解,这样三分嵌套三分最后就可以得到最终的最优解。
code:#include<bits/stdc++.h>
using namespace std;
const double eps=1e-7;
struct point
{
double x;
double y;//坐标的x,y的值
} a,b,c,d,X,Y;//X,Y表示ab与cd上转弯的点
double p,q,r;//速度
double ab,cd;//表示ab,cd的长度
double dis(point A,point B);//求两点之间的距离
double search_ab(double l,double r);//ab上的三分寻找
double search_cd(double ax);//cd上的三分寻找
double suan(double cy);//计算总时间
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>a.x>>a.y>>b.x>>b.y;//表示a,b点的坐标
cin>>c.x>>c.y>>d.x>>d.y;//表示c,d点的坐标
cin>>p>>q>>r;
ab=dis(a,b);//计算距离
cd=dis(c,d);
double temp=search_ab(0,ab);
printf("%0.2lf\n",temp);
}
return 0;
}
double dis(point A,point B)//求两点之间的距离
{
double xx=(A.x-B.x)*(A.x-B.x);
double yy=(A.y-B.y)*(A.y-B.y);
return sqrt(xx+yy+eps);
}
double search_ab(double l,double r)//ab上的三分查找
{
double t1,t2;//表示三分两个点的时间
double mid,emid,temp;
while(r-l>eps)
{
mid=(l+r)/2;
emid=(mid+r)/2;
t1=search_cd(mid);
t2=search_cd(emid);
if(t1<=t2)
r=emid;
else
l=mid;
temp=min(t1,t2);//记录短的时间
}
return temp;
}
double search_cd(double ax)//cd上求三分,ax表示a点到x的距离
{
double temp;
X.x=a.x+(b.x-a.x)*(ax/ab);//按照比例求的点
X.y=a.y+(b.y-a.y)*(ax/ab);//一定是b-a,因为时从a点向b点走
double t1,t2;//时间
double mid,emid;
double l=0,r=cd;
while(r-l>eps)
{
mid=(l+r)/2;
emid=(mid+r)/2;
t1=suan(mid);
t2=suan(emid);
if(t1<=t2)
r=emid;
else
l=mid;
temp=min(t1,t2);//记录短的时间
}
return ax/p+temp;//返回时间
}
double suan(double cy)//cy表示c点到y点的距离
{
Y.x=c.x+(d.x-c.x)*(cy/cd);//按照比例求的点
Y.y=c.y+(d.y-c.y)*(cy/cd);//从c点向d点走,所以d-c
return dis(X,Y)/r+(cd-cy)/q;
//先求两条线段之间的时间,再求y到d点的时间
//因为三分分出来的是cd上不要的地方,所以cd-cy 仔细思考
}