HDU 3400 Line belt(嵌套三分)

来源:互联网 发布:视频检索软件 编辑:程序博客网 时间:2024/05/17 23:16
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

题目大意:
给出两条平行的线段AB, CD,然后一个人在线段AB的A点出发,走向D点,其中,人在线段AB上的速度为P, 在线段CD上的速度为Q,在其他地方的速度为R,求人从A点到D点的最短时间。

                                                              

人所用的时间为 T = X / P + Y / Q + Z / R。当X 和Y都确定的情况下,Z也是一个确定值。所以,所求的函数可以写成: T(X,Y) = F(X) + G(Y)+定值。因为T是一个关于X和Y的函数,而G只是一个关于Y的函数,所以,可以用两层嵌套的三分法解这个方程。首先以X为变量,对T进行三分。在求G的值的时候,以Y为变量,对G进行三分,求出G在对应的X下的最小值。这样就能求出T的最小值了。

如何证明这个题能够用三分解?
首先,F(X)函数是一个单调递增的函数,而G(Y)很明显是一个先递减后递增的函数。两个函数叠加,所得的T(X,Y)函数应该也是一个先递减后递增的函数。故可用三分法解之。

#include<cstdio>#include<iostream>#include<cmath>using namespace std;struct point{    double x,y;} A,B,C,D;double dis(point a,point b){    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}double P,Q,R;double sove_CD(point c,point d,point m){    point l=c,r=d;    point mid,midd;    double k1,k2;    do    {        mid.x=(l.x+r.x)/2;        mid.y=(l.y+r.y)/2;        midd.x=(mid.x+r.x)/2;        midd.y=(mid.y+r.y)/2;        k1=dis(mid,d)/Q+dis(m,mid)/R;        k2=dis(midd,d)/Q+dis(m,midd)/R;         if(k1<k2)            r=midd;        else            l=mid;    }    while(fabs(k1-k2)>=1e-10);    return k1;}double sove(point a,point b,point c,point d){    point l=a,r=b;    point mid,midd;    double k1,k2;    do    {        mid.x=(l.x+r.x)/2;        mid.y=(l.y+r.y)/2;        midd.x=(mid.x+r.x)/2;        midd.y=(mid.y+r.y)/2;        k1=dis(a,mid)/P+sove_CD(c,d,mid);        k2=dis(a,midd)/P+sove_CD(c,d,midd);        if(k1<k2)            r=midd;        else            l=mid;    }    while(fabs(k1-k2)>=1e-10);    return k1;}int main(){    int t;    cin>>t;    while(t--)    {        cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y>>D.x>>D.y;        cin>>P>>Q>>R;        printf("%.2lf\n",sove(A,B,C,D));    }}


0 0
原创粉丝点击