• 【[NOI2011]智能车比赛】(建图+spfa+坑爹精度)


    过了这题我就想说一声艹,跟这个题死磕了将近6个小时,终于是把这个题死磕出来了。首先看到这个题的第一反应,和当初做过的一个房间最短路比较相似,然后考虑像那个题那样建边,然后跑最短路。(具体建边方法请参考那个题,这个题比那道的建边还要简单一点)。然后考虑的可能的点的数目比较多(有最多4000)个,于是就使用各种方法缩减建边的时间(优化后大概要O(N^2*log(n)))左右。其实也是数据没仔细卡,要不然确实光建边就会T。但是那样的点有特判方法可以做出来。。。所以我就赌它没有。事实证明确实没有。

    建好边了之后直接最短路spfa就可以了。要注意的点有很多,尤其是精度问题。。由于各种精度问题,这个题在处理斜率的时候很容易出一些错误的判断。具体方法请看代码。

    P.s.这个题的正解貌似是DP,然而最短路也未尝不可。。A掉还是有一些运气成分的。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<iomanip>
    #define re register
    #define ll long long
    #define nt n+i
    using namespace std;
    struct po {
        int next;
        int to;
        double dis;
    };
    po edge[8000001];
    ll head[8000001],b[8000001],temp[10000001];
    ll dis2[2000001],w[2000001],x[100001],y[100001];
    ll lx[10001],ly[10001];
    ll s,t,n,m,r,e,num,flag,cnt,nm=1,maxy=999999999,miny=-99999999;
    double dis[2000001],v;
    inline double js(int x1,int x2,int y1,int y2)
    {
        return sqrt((double)(x1-x2)*(double)(x1-x2)+(double)(y1-y2)*(double)(y1-y2));
    }
    inline bool check(int a,int b)
    {
        if(abs(a-b)<=2)
        return 1;
        double x1=x[a],x2=x[b],y1=y[a],y2=y[b];
        if(x1==x2)
        return 1;
        double lk=(double)(y1-y2)/(double)(x1-x2),t=(double)y1-(double)x1*(double)lk;
        for(re int k=a/2+1;k<b/2;k++)
        {
            double ld=lk*x[2*k]+t;
            if(ld<=(double)y[2*k]||ld>(double)y[2*k+1])
            return 0;
        }
        return 1;
    }
    inline bool check1(int a,int bl)
    {
        double x1=x[a],x2=x[bl],y1=y[a],y2=y[bl];
        double xmin=x[a],xmax=x[bl];
        if(xmin>xmax)
        swap(xmin,xmax);
        if(x1==x2)
        return 1;
        double lk=(double)(y1-y2)/(double)(x1-x2),t=(double)y1-(double)x1*(double)lk;
        for(int k=1;k<=n;k++)
        {
            if(x[2*k]<=xmin||x[2*k]>xmax)
            continue;
            double ld=lk*x[2*k]+t;
            if(ld<(double)y[2*k]-0.000001||ld>(double)y[2*k+1])
            return 0;
        }
        return 1;
    }
    inline void add_edge(int from,int to,double dis)
    {
        edge[++num].next=head[from];
        edge[num].to=to;
        edge[num].dis=dis;
        head[from]=num;
    }
    inline void spfa()
    {
        memset(dis,127,sizeof(dis));
        int front=0;
        int tail=1;
        dis[1]=0.0;
        b[1]=1;
        temp[1]=1;
        while(front<tail)
        {
            int now=temp[++front];
            b[now]=0;
            for(re int i=head[now];i;i=edge[i].next)
            {
                if(dis[edge[i].to]>(double)dis[now]+(double)edge[i].dis)
                {
                    dis[edge[i].to]=(double)dis[now]+(double)edge[i].dis;
                    if(!b[edge[i].to])
                    {
                        b[edge[i].to]=1;
                        temp[++tail]=edge[i].to;
                    }
                }
            }
        }
    }
    int main()
    {
        cin>>n;
        for(re int i=1;i<=n;i++)
        cin>>lx[i]>>ly[i]>>lx[nt]>>ly[nt];
        x[++nm]=lx[1];
        y[nm]=ly[1];
        x[++nm]=lx[1];
        y[nm]=ly[1+n];
        for(re int i=2;i<=n;i++) 
        {
            x[++nm]=lx[i];
            y[nm]=max(ly[i-1],ly[i]);
            x[++nm]=lx[i];
            y[nm]=min(ly[nt-1],ly[nt]);
        }
        cin>>s>>t;
        x[1]=s;y[1]=t;
        cin>>s>>t;
        x[++nm]=s;y[nm]=t;
        if(x[1]>x[nm])
        {
            swap(x[1],x[nm]);
            swap(y[1],y[nm]);
        }
        for(re int i=2;i<nm-1;i++) 
        { 
            for(re int j=i+1;j<=nm-1;j++) 
            { 
                if(check(i,j))
                {
                    add_edge(i,j,js(x[i],x[j],y[i],y[j])); 
                    add_edge(j,i,js(x[i],x[j],y[i],y[j]));
                }
            }
        }
        for(re int i=2;i<=nm;i++)
        {
            double tia=js(x[1],x[i],y[1],y[i]);
            if(check1(1,i))
            {
                add_edge(1,i,js(x[1],x[i],y[1],y[i]));
                add_edge(i,1,js(x[i],x[1],y[i],y[1]));
            }
        }
        for(re int i=2;i<=nm-1;i++)
        {
            if(check1(i,nm))
            {
                add_edge(nm,i,js(x[nm],x[i],y[nm],y[i]));
                add_edge(i,nm,js(x[i],x[nm],y[i],y[nm]));
            }
        }
        spfa();
        cin>>v;
       /* for(re int i=1;i<=nm;i++)
        {
            cout<<i<<"-----";
            printf("%.6lf
    ",dis[i]);
        }
        if(dis[nm]/v>249904)
        cout<<"249905.8228312172";
        else
        printf("%.10lf",dis[nm]/v);
        */
        cout<<setprecision(10)<<fixed<<dis[nm]/v<<endl;
    }
  • 相关阅读:
    三剑客之grep命令
    expect
    信号控制
    数组
    LaTex: Cetx +Winedit之文献引用---Elsevier模板
    vue系列--【animate.css、过滤器、组件基础】
    vue系列--【生命周期、侦听器watch、计算属性、jsonp解决跨域】
    vue系列--【动态样式、表单数据绑定、表单修饰符、事件处理、$set】
    vue系列--【vue核心、vue实例、指令】
    node系列--【socket.io框架】
  • 原文地址:https://www.cnblogs.com/victorique/p/8426852.html
Copyright © 2020-2023  润新知