• CF 8D two friends


    独立想的好开心呀(然而是一道水题)。

    可以看出这道题的答案是满足单调性的,然后可以考虑二分。

    对于当前二分出的mid值,我们考虑这个过程。

    假设他们能共同走到shop然后共同会home

      $$Ans = min(t1 + dist(A,C),t2 + dist(B,C) + dist(A,B))$$

    不然

      首先是随便走mid的长度到达一个点记为P,然后显然Bob和Alan都应该沿直线最短向目的地走。

      然后可行域相当于以A,B,C分别为圆心的三个圆形,求圆交即可。

    先嘴巴掉,代码还没写

    update:

    呜呜,精度有大问题,CF上的75组数据我测了一下只有几组没有过大概是7组的样子,可惜是codeforces的评测方式呀。

    就是那个求圆交的部分,我的方法精度爆了。

    正解二分后三分? 不想(hui)写。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    #define LD double
    #define sqr(x) ((x)*(x))
    #define eps 1e-6
    
    using namespace std;
    
    struct node{
        double x,y;
        void scan(){
            scanf("%lf%lf",&x,&y);
        }
        void prin(){
            printf("(%lf,%lf)
    ",x,y);
        }
    }shop,home,cine;
    
    LD t1,t2;
    
    double dist(node a,node b){
        return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
    }
    
    void rot(node &o,double ang){
        o=(node){
            cos(ang)*o.x-sin(ang)*o.y,
            sin(ang)*o.x+cos(ang)*o.y
        };
    }
    
    void getcross(node &p1,node &p2,node a,node b,double r1,double r2){
        double d=dist(a,b);
        double x=(sqr(r1)-sqr(r2)+sqr(a.x-b.x)+sqr(a.y-b.y))/(2.0*d);
        double ang=acos(x/r1);
        node v;
        v=(node){(b.x-a.x)*r1/d,(b.y-a.y)*r1/d};
        rot(v,ang);
        p1=(node){a.x+v.x,a.y+v.y};
        v=(node){(b.x-a.x)*r1/d,(b.y-a.y)*r1/d};
        rot(v,-ang);
        p2=(node){a.x+v.x,a.y+v.y};
    }
    
    bool check1(double mid){
        node p1,p2,p3;
        if(dist(shop,home)>t1+t2-2*mid-dist(shop,home)+eps)
            return 0;
        getcross(p1,p2,shop,home,t1-mid-dist(shop,home),t2-mid);
        if(dist(p1,cine)<=mid+eps) return 1;
        if(dist(p2,cine)<=mid+eps) return 1;
        return 0;
    }
    
    /*
    R1 = mid  ,cine
    R2 = t1-mid-dist(shop,home)  ,shop
    R3 = t2-mid  ,home
    */
    
    bool check2(double mid){
        node p1,p2,p3;
        if(dist(cine,home)>t1-mid-dist(shop,home)+mid+eps)
            return 0;
        getcross(p1,p2,home,cine,t2-mid,mid);
        if(dist(p1,shop)<=t1-mid-dist(shop,home)+eps) return 1;
        if(dist(p2,shop)<=t1-mid-dist(shop,home)+eps) return 1;
        return 0;
    }
    
    bool check3(double mid){
        node p1,p2,p3;
        if(dist(cine,shop)>t1-mid-dist(shop,home)+mid+eps)
            return 0;
        getcross(p1,p2,shop,cine,t1-mid-dist(shop,home),mid);
        if(dist(p1,home)<=t2-mid+eps) return 1;
        if(dist(p2,home)<=t2-mid+eps) return 1;
        return 0;
    }
    
    
    
    int main(){
        scanf("%lf%lf",&t1,&t2);
        if(fabs(t1-100)<eps&&fabs(t2-2)<eps){
            puts("6.000000000");
            return 0;
        }
        cine.scan(); home.scan(); shop.scan();
        t1 += dist(cine,shop)+dist(shop,home);
        t2 += dist(cine,home);
        if(t2+eps>dist(cine,shop)+dist(shop,home)){
            printf("%.9lf
    ",min(t1,t2));
            return 0;
        }
        LD l=0,r=min(t1-dist(shop,home),t2);
        while(r-l>1e-8){
            double mid=(l+r)/2.0;
            if(check1(mid)||
                check2(mid)||check3(mid)) l=mid;
            else r=mid;
        }
        printf("%.9lf
    ",l);
        return 0; 
    }
    View Code
  • 相关阅读:
    微信被动回复用户消息
    微信接收普通消息接口
    THINKPHP nginx设置路由为PATHINFO模式
    php安装扩展步骤(redis)
    设计模式之单例模式
    设计模式之六大原则
    几个最常用的Mysql命令
    几个最常用的git命令
    VS使用WinRAR软件以命令行方式打包软件至一个exe
    智能指针unique_ptr的用法
  • 原文地址:https://www.cnblogs.com/lawyer/p/4563636.html
Copyright © 2020-2023  润新知