题面:BZOJ1857 Luogu2571
观察题目加上一定分析计算画图像等等可以得出,从某一条传送带的某一位置直接到达终点的函数是一个二次函数
这一结论同样可以推到两条传送带上
我们看作从第一条传送带的某一点直接到达第二条传送带的某一点(把这个点当终点好了),再沿着传送带到终点
这样我们就可以搞一搞喜闻乐见的三分啦OWO
这个其实是三分套三分啦,首先三分第一条传送带的点,然后把这个点当终点,三分第二条传送带的某一点,这样就满足一开始得出的结论了
如何计算路径长度和时间?
路径分三段,从起点沿传送带1到第一个点,第一个点直线到第二个点,第二个点沿传送带2到终点
首先我们三分的是每条传送带的指定点到起点(终点)的长度,所以第一段和最后一段无需计算
第二段嘛。。。我们首先计算出两个点相对于整条传送带位置的比例(举个例子某一点到起点的距离与整条的长比例是1:4)
这样我们就可以快速地算出每个点的具体坐标了
x坐标:该传送带起始点x坐标+比例*(该传送带终点x坐标-该传送带起点x坐标)
y坐标同理
然后直接勾股定理计算距离即可
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <ctime>
#include <map>
#include <queue>
#include <cstdlib>
#include <string>
#include <climits>
#include <set>
#include <vector>
using namespace std;
typedef double D;
D ax,ay,bx,by,cx,cy,dx,dy,a,b,c,L1,L2;
inline D sqr(D x){return x*x;}
inline D sanfen(D x){
D wx=L1?ax+(bx-ax)*(x/L1):ax,wy=L1?ay+(by-ay)*(x/L1):ay;//第一条传送带x点的坐标
D ans,l=0,r=L2;
while(r-l>1e-9){
D l1=l+(r-l)/3,l2=l1+(r-l)/3;
D vx=L2?cx+(dx-cx)*(l1/L2):cx,vy=L2?cy+(dy-cy)*(l1/L2):cy;//第二条传送带l1点的坐标
D k1=x/a+(L2-l1)/b+sqrt(sqr(vx-wx)+sqr(vy-wy))/c;//l1总时间
vx=L2?cx+(dx-cx)*(l2/L2):cx,vy=L2?cy+(dy-cy)*(l2/L2):cy;//第二条传送带l2点的坐标
D k2=x/a+(L2-l2)/b+sqrt(sqr(vx-wx)+sqr(vy-wy))/c;//l2总时间
if(k1-k2<1e-9&&k2-k1<1e-9)l=l1,r=l2;
else if(k2-k1>1e-9)r=l2;
else l=l1;
}
D vx=L2?cx+(dx-cx)*(l/L2):cx,vy=L2?cy+(dy-cy)*(l/L2):cy;
ans=x/a+(L2-l)/b+sqrt(sqr(vx-wx)+sqr(vy-wy))/c;
return ans;
}
int main()
{
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy,&dx,&dy);
scanf("%lf%lf%lf",&a,&b,&c);
L1=sqrt(sqr(ax-bx)+sqr(ay-by));L2=sqrt(sqr(cx-dx)+sqr(cy-dy));
D l=0,r=L1;
while(r-l>1e-9){
D l1=l+(r-l)/3,l2=l1+(r-l)/3;
D k1=sanfen(l1),k2=sanfen(l2);
if(k1-k2<1e-9&&k2-k1<1e-9)l=l1,r=l2;
else if(k2-k1>1e-9)r=l2;
else l=l1;
}
printf("%.2lf",sanfen(l));//计算答案
return 0;
}