您的位置:首页 > 其它

hdu 3400 Line belt(三分套三分)

2016-12-06 10:06 405 查看
题意:

在一个二维空间中给出两条线段AB,CD,线段AB,CD上的运动速度分别为p,q。在这两条线段之外的空间上运动的速度为r。求从A到D的最短时间。

思路:

我们可以列出式子time=ab/p+cd/q+bc/r;ab表示在线段AB上运动的距离,cd在线段CD上运动距离,bc表示从线段AB到CD运动的距离。可以看出来,这个式子是一个凹形函数而time2=cd/q+bc/r也是一个凹形函数,而这个式子其实只有ab,cd两个未知量,所以我们可以用两次三分求解。把登时写为time=ab/p+time2.首先对ab三分,再对cd三分求time2,即可求解。

ps:在这种求解方法中,中间运用了比较多的除法,导致精度损失,所以再开方前加一个eps,防止开方后的值比真实值小。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
const double eps=1e-8;
double p, q, r;
double AB, CD, ax, ay, bx, by, cx, cy, dx, dy;
double AX, AY, CX, CY;
double dis(double ax, double ay, double bx, double by)
{
return sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by)+eps);
}
double f2(double mid)
{
double tim=0;
tim+=(CD-mid)/q;
CX=cx+(dx-cx)*mid/CD;
CY=cy+(dy-cy)*mid/CD;
double L=dis(AX, AY, CX, CY);
tim+=L/r;
return tim;
}

double f1(double x)
{
double tim=x/p;
AX=ax+x/AB*(bx-ax);
AY=ay+x/AB*(by-ay);
CD=dis(cx,cy,dx,dy);
double left=0.0, right=CD;
double mid, mmid;
while(right-left>=eps)
{
mid=left+(right-left)/3;
mmid=right-(right-left)/3;
if(f2(mid)>=f2(mmid))
{
left=mid;
}
else
{
right=mmid;
}
}
return f2((mid+mmid)/2)+tim;
}

double three_devide1(double low,double up)
{
double m1,m2;

while(up-low>=eps)
{
m1=low+(up-low)/3;
m2=up-(up-low)/3;

if(f1(m1)>=f1(m2))
low=m1;
else
up=m2;
}
return f1((m1+m2)/2);
}

int main()
{
int t;

cin>>t;
while(t--)
{
cin>>ax>>ay>>bx>>by>>cx>>cy>>dx>>dy;
cin>>p>>q>>r;
AB=dis(ax,ay,bx,by);
double left=0.0, right=AB;
double ans=three_devide1(left, right);
printf("%.2lf\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: