HDU problem f

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  仔细思考
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值