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
【来源】
首先在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;
}