syoj.1827. 线段传送带题解
省流:三分套三分。
在二维平面上有两个传送带,一个从 A 点到 B 点,一个从 C 点到 D 点,速度分别是 p 和 q,在平面内其他点的速度为 r。求 A 点到 D 点的最小速度。
考虑从 A 到 D 的路程一定是 \(AE+EF+FD\),即通过这两个点连接这两个传送带,E 在第一个传送带上,F 同理在第二个。
所以答案求一个 \({(dis(A,E)/p+dis(E,F)/r+dis(F,D)/q)}_{min}\)。 这是个二元函数。
不妨将这个式子拆成两个函数,以确定参数 E,对于 \(f(E)\) 解出一个 F 使得 \((dis(E,F)/r+dis(F,D)/q)min\)。那这个单峰函数可以用三分求最值。
同理,上式外面再套一个求 E 的式子,解出一个 E 使得 \((dis(A,E)/p+f(E))min\)。这个单峰函数也可以用三分求解。
于是三分套三分。
#include<bits/stdc++.h>
#define db double
using namespace std;
const db eps=1e-6;
db ax,ay,bx,by,cx,cy,dx,dy,p,q,r;
db dis(db x,db y,db xx,db yy){
return sqrt((yy-y)*(yy-y)+(xx-x)*(xx-x));
}
db f3(db x,db y,db xx,db yy){//E & F
return dis(x,y,xx,yy)/r+dis(xx,yy,dx,dy)/q;
}
db f2(db ex,db ey){//F
db lx=cx,ly=cy,rx=dx,ry=dy;//CD
while(dis(lx,ly,rx,ry)>eps){
db x=(rx-lx)/3.0,y=(ry-ly)/3.0;
db lmidx=lx+x,lmidy=ly+y,rmidx=rx-x,rmidy=ry-y;
db ans1=f3(ex,ey,lmidx,lmidy);
db ans2=f3(ex,ey,rmidx,rmidy);
if(ans2-ans1>eps) rx=rmidx,ry=rmidy;
else lx=lmidx,ly=lmidy;
}
return f3(ex,ey,lx,ly);
}
db f1(){//E
db lx=ax,ly=ay,rx=bx,ry=by;
while(dis(lx,ly,rx,ry)>eps){//AB
db x=(rx-lx)/3.0,y=(ry-ly)/3.0;
db lmidx=lx+x,lmidy=ly+y,rmidx=rx-x,rmidy=ry-y;
db ans1=f2(lmidx,lmidy)+dis(ax,ay,lmidx,lmidy)/p;
db ans2=f2(rmidx,rmidy)+dis(ax,ay,rmidx,rmidy)/p;
if(ans2-ans1>eps) rx=rmidx,ry=rmidy;
else lx=lmidx,ly=lmidy;
}
return f2(lx,ly)+dis(ax,ay,lx,ly)/p;
}
int main(){
scanf("%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy,&p,&q,&r);
printf("%.2lf",f1());
return 0;
}