• 【bzoj1857】 Scoi2010—传送带


    http://www.lydsy.com/JudgeOnline/problem.php?id=1857 (题目链接)

    题意

      给出两条线段AB和CD,在AB上的速度为P,在CD上的速度为Q,在AB,CD之外的平面上速度为R,求从A到D的最短时间。

    Solution 

      三分套三分。 

      三分法是个很基础的东西,当问题的答案呈现出的函数图像是单峰的那么就可以使用三分法求出它的最值,具体操作与二分法差不多。 

      可这道题为什么可以用三分法呢,也就是说它为什么是单峰的,我也不会= =,果断翻题解。 
      

      首先,我们用三分法,最基本的是要证明那个人一定是沿着如下路径走的:从A沿着AB走一段,再穿越到CD上某一点,最后到终点。证明如下:不妨假设p>q>r,因为当r>max(p,q)时没什么好讨论的,而p,q的大小没什么关系。那么假设这人从AB上一点X离开,那么如果它不沿着刚刚的路径,则它一定会沿着某个路径回到AB上一点Y,显然X->Y的最快方法是沿着AB走,因为这样距离最短而速度最快。证完。 
      那么,如果我们假设它从AB上一点X出发到CD上一点Y再到终点,那么当X为定点时,时间与CY长度是成单峰函数的,证明如下: 
    这里写图片描述
      当s>=q时,显然时间随着CY的增大而减小,显然是单峰函数,因此不妨设s<q。过点X作XH⊥CD,显然当Y在CH上时时间增大,不做讨论。当Y在HD上时,设XH=h,HY=t,那么Y点比D点的时间节约(当Y点比D点时间长时该式为负号):t/q-(sqrt(t^2+h^2)-h)/s=t/q+h/s-sqrt(t^2+h^2)/s,显然sqrt(t^2+h^2)增长是没有t的增长快的,因此一开始该式为正数,时间减少;但是当t增大时,sqrt(t^2+h^2)的增大速度不断变快最终趋向于t的增大速度,不要忘了q>s,所以该式最终会变为负数并且一定会越变越小,时间不断增大。综上所述:时间先单调递减再单调递增,证完。 
      然而我并不会证明从AB上一点X离开的最优时间,这个函数与AX成单峰函数关系。。。

      于是就这样挖了个坑。。。最关键的地方还是没有讲到。

    代码

    // bzoj1857
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<set>
    #define eps 1e-9
    #define inf 2147483640
    #define LL long long
    #define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
    using namespace std;
    inline LL getint() {
        LL x=0,f=1;char ch=getchar();
        while (ch>'9' || ch<'0') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int ax,bx,cx,dx,ay,by,cy,dy,p,q,r;
    
    double dis(double x1,double y1,double x2,double y2) {
        return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
    }
    double cal(double x,double y) {
        double x1,y1,x2,y2,t1,t2;
        double lx=cx,ly=cy,rx=dx,ry=dy;
        while (fabs(lx-rx)>eps || fabs(ly-ry)>eps) {
            x1=lx+(rx-lx)/3;x2=lx+(rx-lx)/3*2;
            y1=ly+(ry-ly)/3;y2=ly+(ry-ly)/3*2;
            t1=dis(ax,ay,x,y)/p+dis(x,y,x1,y1)/r+dis(x1,y1,dx,dy)/q;
            t2=dis(ax,ay,x,y)/p+dis(x,y,x2,y2)/r+dis(x2,y2,dx,dy)/q;
            if (t1>t2) lx=x1,ly=y1;
            else rx=x2,ry=y2;
        }
        //return min(t1,t2);
        return dis(ax,ay,x,y)/p+dis(x,y,lx,ly)/r+dis(lx,ly,dx,dy)/q;
    }
    int main() {
        scanf("%d%d%d%d",&ax,&ay,&bx,&by);
        scanf("%d%d%d%d",&cx,&cy,&dx,&dy);
        scanf("%d%d%d",&p,&q,&r);
        double x1,x2,y1,y2,t1,t2;
        double lx=ax,ly=ay,rx=bx,ry=by;
        while (fabs(rx-lx)>eps || fabs(ry-ly)>eps) {
            x1=lx+(rx-lx)/3;x2=lx+(rx-lx)/3*2;
            y1=ly+(ry-ly)/3;y2=ly+(ry-ly)/3*2;
            t1=cal(x1,y1);t2=cal(x2,y2);
            if (t1>t2) lx=x1,ly=y1;
            else rx=x2,ry=y2;
        }
        printf("%.2f",cal(lx,ly));
        //printf("%.2f",min(t1,t2));
        return 0;
    }
    

      

  • 相关阅读:
    map方法,以及filter方法的使用
    detach与remove区别,以及detach保留被删除的元素数据,使用
    jQuery 文档操作
    javascript 清空数组的方法
    jquery遍历数组的方式
    Oracle表空间不足处理
    css 文本超出2行就隐藏并且显示省略号
    Vim中的寄存器
    spacemacs怎样配置编辑器显示行号?
    Docker考前突击
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914273.html
Copyright © 2020-2023  润新知