http://acm.hdu.edu.cn/game/entry/problem/list.php?chapterid=4§ionid=1
经典的三分
HDU 3400 Line belt (三分再三分)
ACM
题目地址:
HDU 3400 Line belt
题意:
就是给你两条线段AB , CD ,一个人在AB以速度p跑,在CD上以q跑,在其他地方跑速度是r。问你从A到D最少的时间。
分析:
先三分AB上的点,再三分CD上的点即可。
证明:
设E在AB上,F在CD上。
令人在线段AB上花的时间为:f = AE / p
,人走完Z和Y所花的时间为:g = EF / r + FD / q
。
f函数是一个单调递增的函数,而g很明显是一个先递减后递增的函数。两个函数叠加,所得的函数应该也是一个先递减后递增的函数。故可用三分法解之。
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=6*1e3+107;
const double pi=acos(-1.0);
const double eps=1e-8;
typedef long long ll;
struct node{
double x,y;
}a,b,c,d,e,f;
double p,q,r;
double dis(node l,node r){
return sqrt( (l.x-r.x)*(l.x-r.x)+ (l.y-r.y)*(l.y-r.y));
}
double calculate(double point)//e->f f->d
{
f.x=c.x+(d.x-c.x)*point;
f.y=c.y+(d.y-c.y)*point;
return dis(e,f)/r+dis(f,d)/q;
}
double inter(double point)//a->e
{
e.x=a.x+(b.x-a.x)*point;
e.y=a.y+(b.y-a.y)*point;
double l=0,r=1,mid,mmid,cost;
while(r-l>eps)
{
mid=(l+r)/2;
mmid=(mid+r)/2;
cost=calculate(mid);
if(cost<=calculate(mmid)) r=mmid;
else l=mid;
}
return dis(a,e)/p+cost;
}
double solve()
{
double l=0,r=1,mid,mmid,cost;
while(r-l>eps)
{
mid=(l+r)/2;
mmid=(mid+r)/2;
cost=inter(mid);
if(cost<=inter(mmid)) r=mmid;
else l=mid;
}
return cost;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>a.x>>a.y >>b.x>>b.y;
cin>>c.x>>c.y >>d.x>>d.y;
cin>>p>>q>>r;
printf("%.2lf\n",solve());
}
return 0;
}