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;
}

 

posted @ 2018-05-04 16:15  Star_Feel  阅读(230)  评论(0编辑  收藏  举报