• CF187B AlgoRace


    CF187B AlgoRace

    洛谷传送门

    题意翻译

    有nn 个城市,两两之间有直接连边,还有mm 辆车。

    已知这mm 辆车在(i,j)(i,j) 边上需要w_{i,j}w**i,j 的时间,但是你可以在到达一个城市之后选择换车,换车视为瞬间完成。对于每组询问(s,t,k)(s,t,k) ,求s o tst 的最短时间,其中换车总次数不超过k-1k−1 ,即全程使用的车次不超过kk

    询问有rr 组数据。其中

    n,mle 60 , w_{i,j}le 10^6 , rle 10^5n,m≤60,w**i,j≤106,r≤105 ;

    1le s,tle n,kle 10001≤s,tn,k≤1000 .

    感谢@frankchenfu 提供的翻


    题解:

    一眼DP,看到这个数据范围觉得应该是多维状态。

    所以直接按题意设:

    (dp[i][j][k])表示从i到j一共使用的车次不超过k的最短时间

    那么可以看出,这个转移和中转点有关系。也就是枚举断点,类似(Floyd)的转移。但是还有这个换车的一维比较难搞。

    稍加思索,觉得转移应该是这样的:

    [dp[i][j][k]=min(dp[i][l][k-1]+dp[l][j][0])quad(lin (1,n)) ]

    也就是,先换不超过k-1次车,最后不换车直接到达,因为断点处必然换一次车。

    那么初值也就是不换车直达的时间。这个需要开始就做一遍松弛。

    然后就看代码吧:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxq=1e5+5;
    int n,m,r,maxx;
    int dp[62][62][62];
    //dp[i][j][k]表示i->j换k次车的最小时间
    int a[62][62][62];
    //a[k][i][j]表示i->j的原始时间
    int q[maxq][3];
    int main()
    {
        scanf("%d%d%d",&n,&m,&r);
        for(int k=1;k<=m;k++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    scanf("%d",&a[k][i][j]);
        for(int i=1;i<=r;i++)
        {
            scanf("%d%d%d",&q[i][0],&q[i][1],&q[i][2]);
            maxx=max(maxx,q[i][2]);
        }
        maxx=min(maxx,n);
        for(int op=1;op<=m;op++)
            for(int k=1;k<=n;k++)
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        a[op][i][j]=min(a[op][i][j],a[op][i][k]+a[op][k][j]);
        memset(dp,127,sizeof(dp));
        for(int op=1;op<=m;op++)
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    dp[i][j][0]=min(dp[i][j][0],a[op][i][j]);
        for(int k=1;k<=maxx+1;k++)
        {
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    dp[i][j][k]=dp[i][j][k-1];
            for(int l=1;l<=n;l++)
                for(int i=1;i<=n;i++)
                    for(int j=1;j<=n;j++)
                        dp[i][j][k]=min(dp[i][j][k],dp[i][l][k-1]+dp[l][j][0]);
        }
        for(int i=1;i<=r;i++)
        {
            q[i][2]=min(q[i][2],maxx);
            printf("%d
    ",dp[q[i][0]][q[i][1]][q[i][2]]);
        }
        return 0;
    }
    
  • 相关阅读:
    macOS下Go语言开发环境的搭建
    yii使用createCommand()增删改查
    php in_array问题,0与字符串比较问题
    PHP shortURL
    redis集群批量删除某些key
    git tag的用法
    JSON Web Token(JWT)
    C# Stopwatch详解 转
    转::CString 操作指南
    MFC VC 中 TreeView 解析
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14059503.html
Copyright © 2020-2023  润新知