• [SCOI2010] 传送带


    三分套三分,数学

    传送门:$>here<$


    题意:平面上有两条线段$AB$和$CD$,人在$AB$上通行速度为$P$,在$CD$上为$Q$,在平面内则为$R$。问从$A$到$D$的最短时间。

    数据范围:均小于1000


    $Solution$

    我们发现我们的路径一定是沿着$AB$走一段,然后横跨平面,再在$CD$上走一段的。而问题就在于在这两条线段上究竟走多少。

    假设我们在$AB$上一直走到$E$,在$CD$上从$F$开始走。那么答案是一个关于$E,F$的二元函数。我们要求这个二元函数的最小值。通过观察我们发现(如何证明???)这两个元的取值都是凸性的,因此三分套三分求最小值即可。

    我选择二分距离。设$AE$为$k$。现在要求$E$的坐标,用相似可得$X_E=X_A+dfrac{AE}{AB}(X_B-X_A)$。其他的同理

    反思

    关于此类距离问题跟二分三分好像都有密切关系。

    $my code$

    坑点在于如果$A$与$B$重合(或是$C$与$D$重合)时,会$nan$。因此特判。

    /*By DennyQi 2018*/
    #include <cstdio>
    #include <queue>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int MAXN = 10010;
    const int MAXM = 20010;
    const int INF = 1061109567;
    inline int Max(const int a, const int b){ return (a > b) ? a : b; }
    inline int Min(const int a, const int b){ return (a < b) ? a : b; }
    inline int read(){
        int x = 0; int w = 1; register char c = getchar();
        for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
        if(c == '-') w = -1, c = getchar();
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
    }
    struct Coordinate{
        double x,y;
    };
    Coordinate A,B,C,D;
    double Q,P,R,l,r,mid,mmid,AB,CD;
    inline double sqr(double X){
        return X*X;
    }
    inline double ABS(double X){
        if(X<0) return -X;
        return X;
    }
    inline double get_dis(Coordinate A, Coordinate B){
        return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
    }
    inline double Calculate(double k, double w){
        double res = k/P + w/Q;
        Coordinate E,F;
        if(AB > 0){
            E.x = A.x + k/AB * (B.x-A.x), E.y = A.y + k/AB * (B.y-A.y);
        }
        else{
            E = A;
        }
        /*防nan*/
        if(CD > 0){
            F.x = D.x - w/CD * (D.x-C.x), F.y = D.y - w/CD * (D.y-C.y);
        }
        else{
            F = C;
        }
        res += get_dis(E,F) / R;
        return res;
    }
    inline double calc(double k){
        double l = 0, r = CD, mid, mmid;
        while(r - l >= 1e-6){
            mid = (l+r) / 2.0;
            mmid = (mid+r) / 2.0;
            if(Calculate(k,mid) < Calculate(k,mmid)){
                r = mmid;
            }else{
                l = mid;
            }
        }
        return Calculate(k,l);
    }
    int main(){
        scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
        scanf("%lf%lf%lf%lf",&C.x,&C.y,&D.x,&D.y);
        scanf("%lf%lf%lf",&P,&Q,&R);
        AB = get_dis(A,B);
        CD = get_dis(C,D);
        l = 0, r = AB;
        do{
            mid = (l+r) / 2.0;
            mmid = (mid+r) / 2.0;
            if(calc(mid) < calc(mmid)){
                r = mmid;
            }else{
                l = mid;
            }
        }while(r - l >= 1e-6);
        printf("%.2f", calc(l));
        return 0;
    }
  • 相关阅读:
    此类目的是防治序列化Json字符串时的循环引用问题-------最好解决方案
    Json.Net学习笔记
    深入理解javascript原型和闭包(完结)
    SDL 威胁建模工具入门 threat modeling tool
    .NET 4.0 中的契约式编程
    MVC调用部分视图PartialView
    visual studio 常识
    【阿里云产品评测】小鸡咕咕的初体验
    【阿里云入门产品免费试用半年】加入微博话题+“最”炫推荐理由,得精美小礼物
    镜像公测招募啦!!!用镜像开通云服务器,限时免费体验!!
  • 原文地址:https://www.cnblogs.com/qixingzhi/p/9919034.html
Copyright © 2020-2023  润新知