1439:【SCOI2010】传送带

1439:【SCOI2010】传送带

时间限制: 2000 ms 内存限制: 65536 KB
提交数: 386 通过数: 212

【题目描述】

在一个2维平面上有两条传送带,每一条传送带可以看成是一条线段。两条传送带分别为线段AB和线段CD。lxhgww在AB上的移动速度为P,在CD上的移动速度为Q,在平面上的移动速度R。现在lxhgww想从A点走到D点,他想知道最少需要走多长时间。

【输入】

输入数据第一行是4个整数,表示A和B的坐标,分别为Ax,Ay,Bx,By
第二行是4个整数,表示C和D的坐标,分别为Cx,Cy,Dx,Dy
第三行是3个整数,分别是P,Q,R

【输出】
输出数据为一行,表示lxhgww从A点走到D点的最短时间,保留到小数点后2位
【输入样例】
0 0 0 100
100 0 100 100
2 2 1
【输出样例】
136.60
【提示】
【数据范围】

对于100%的数据,1≤ Ax,Ay,Bx,By,Cx,Cy,Dx,Dy≤1000
1≤P,Q,R≤10

【来源】

No

首先在AB线段上固定一个点E再在CD线段上寻找点F使得f(x)=EF/R+FD/Q得最小值,f(x)为单峰函数用三分法寻找,然后因为f(x)min+AF/P也是单峰函数所以用三分套三分解决问题。


注意:y1 y0在头文件cmath中已经声明,不能再次声明否则提交system error。

#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
double x1,x2,y2,x3,y3,x4,y4,ys1,sa,sb,sn;
double Ls(double x,double y,double z,double a) {return sqrt((x-z)*(x-z)+(y-a)*(y-a));}
double time(double xs,double ys,double xf,double yf)
{
    double l1=Ls(xs,ys,x1,ys1);//点到x1,ys1距离
    double d=Ls(xs,ys,xf,yf);//两点之间的距离
    double l2=Ls(xf,yf,x4,y4);
    return l1/sa+l2/sb+d/sn;
}
double dis(double x ,double y)
{
    double l=0,r=1,exp=1e-11;
    while(r-l>=exp)
    {
        double mid=(l+r)/2;
        double midmid=(l+mid)/2;
        double xx=x3+(x4-x3)*mid;//比例
        double yy=y3+(y4-y3)*mid;
        double xs=x3+(x4-x3)*midmid;
        double ys=y3+(y4-y3)*midmid;
        if(time(x,y,xx,yy)<time(x,y,xs,ys))
            l=midmid;
        else r=mid;
    }
    double xx=x3+(x4-x3)*l;
    double yy=y3+(y4-y3)*l;
    return time(x,y,xx,yy);
}
int main()
{
    cin >>x1>>ys1>>x2>>y2>>x3>>y3>>x4>>y4;
    cin >> sa>>sb>>sn;
    double l=0,r=1;//比例
    double exp=10e-11;
    while(r-l>=exp)//三分法
    {
    double mid=(l+r)/2;
    double xx=x1+(x2-x1)*mid;//按照比例确定位置
    double yy=ys1+(y2-ys1)*mid;
    double midmid=(l+mid)/2;//
    double xc=x1+(x2-x1)*midmid;
    double yc=ys1+(y2-ys1)*midmid;
    double a=dis(xx,yy),b=dis(xc,yc);
    if(a<b)
    l= midmid;//找较大时间接近极小值
    else r=mid;
    }

    double xx=x1+(x2-x1)*l;
    double yy=ys1+(y2-ys1)*l;
    double nb=dis(xx,yy);
   cout<<fixed<<setprecision(2)<<nb<<endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值