BZOJ1857: [Scoi2010]传送带
【传送门:BZOJ1857】
简要题意:
在一个平面直角坐标系中,给出A,B,C,D的坐标,AB有一条线段,CD有一条线段
如果在AB上行走,速度为P,如果在CD上行走,速度为Q,如果不在这两条线段上,而是在平面上行走,则速度为R
求出从A走到D的最少时间
题解:
三分套三分模版
首先可以发现从AB上的某个点到D点的距离是一个二次函数,而从这个点到CD上的点的距离也是个二次函数
所以三分套三分求就可以了
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #define eps 1e-4 using namespace std; double Ax,Ay,Bx,By,Cx,Cy,Dx,Dy; double K1,B1,K2,B2; double P,Q,R; double dis(double x1,double y1,double x2,double y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));} double getval(double x1,double x2,int xy1,int xy2) { double y1,y2; if(xy1==1) y1=x1,x1=Ax; else y1=K1*x1+B1; if(xy2==1) y2=x2,x2=Cx; else y2=K2*x2+B2; return dis(Ax,Ay,x1,y1)/P+dis(x1,y1,x2,y2)/R+dis(x2,y2,Dx,Dy)/Q; } double sanfen2(double x,int xy1) { int xy2=0; double l=min(Cx,Dx),r=max(Cx,Dx); if(abs(l-r)<=eps) xy2=1,l=min(Cy,Dy),r=max(Cy,Dy); while(r-l>=eps) { double lm=l+(r-l)/3.0,rm=r-(r-l)/3.0; double v1=getval(x,lm,xy1,xy2); double v2=getval(x,rm,xy1,xy2); if(v1>=v2) l=lm; else r=rm; } return getval(x,l,xy1,xy2); } double sanfen() { int xy1=0; double l=min(Ax,Bx),r=max(Ax,Bx); if(abs(l-r)<=eps) xy1=1,l=min(Ay,By),r=max(Ay,By); while(r-l>=eps) { double lm=l+(r-l)/3.0,rm=r-(r-l)/3.0; double v1=sanfen2(lm,xy1),v2=sanfen2(rm,xy1); if(v1>=v2) l=lm; else r=rm; } return sanfen2(l,xy1); } int main() { scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&Ax,&Ay,&Bx,&By,&Cx,&Cy,&Dx,&Dy); scanf("%lf%lf%lf",&P,&Q,&R); if(Ax==Bx) K1=0.0; else K1=(Ay-By)/(Ax-Bx); B1=Ay-K1*Ax; if(Cx==Dx) K2=0.0; else K2=(Cy-Dy)/(Cx-Dx); B2=Cy-K2*Cx; printf("%.2lf\n",sanfen()); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚