zoukankan      html  css  js  c++  java
  • P1613 跑路——倍增思想,floyd

    https://www.luogu.org/problemnew/show/P1613

    他有一个跑路机器,每次只能跑2k   (单位)路程,每相邻两个点的路程为1,也就是说如果连边1——》2——》3——》4——》5,路径长度为4,那么他可以一次从1跳到5;

    n<=50;

    我们要找的不是最短路径,而是一条路路程二进制数中1的个数最少;

    这数据范围floyd已经够了,但是我们要提前处理一下连边;

    我们将相距2 距离的两点距离设为1,这样再跑最短路就是正确答案;、

    倍增思想体现在预处理上,;

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn=100;
    int g[maxn][maxn][maxn],n,m;
    ll dis[maxn][maxn];
    
    
    void maker_road()
    {
        for(int b=0;b<=64;b++)
        {
            for(int k=1;k<=n;k++)
            {
                for(int i=1;i<=n;i++)
                {
                    for(int j=1;j<=n;j++)
                    {
                        if(g[i][k][b-1]&&g[k][j][b-1])
                        {
                            g[i][j][b]=1;
                            dis[i][j]=1;
                        }
                    }
                }
            }
        }
    }
    
    void floyd()
    {
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                //    if(dis[i][k]+dis[k][j]<dis[i][j])
                    //{
                        dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);
                    //}
                }
            }
        }
    }
    int main()
    {
        memset(dis,0x3f,sizeof(dis));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            g[x][y][0]=1;dis[x][y]=1;
        }
        maker_road();
        floyd();
        printf("%lld
    ",dis[1][n]);
        return 0;
    }

    这里面的memset里面要开0x3f,开127会错出现负数,不知道为什么;

    感谢 the_Death(https://www.luogu.org/space/show?uid=145411)的解答

    {

     因为在弗洛伊德算法里面有dis[i][j]=min(dis[i][k]+dis[k][j],dis[i][j]);,

    并且你无法保证所有的dis[][]的所有都会被更新为1的个数,

    这就表示有些dis[][]中会以memset给的初值进行加法运算。

    而由于memset的特性,你在赋初值的时候赋0x3f也就是127,它的加法会爆long long。

    }

    这个博客里面有memeset的用法技巧

     https://blog.csdn.net/Vmurder/article/details/46537613

  • 相关阅读:
    WPF 绘图 和动画
    BZOJ 4028 分块
    操作系统与计算机网络
    go排序-基数排序
    go排序-睡眠排序
    go排序-堆排序
    go排序-构建大顶堆
    go排序 插入排序
    go排序-选择排序
    go排序-冒泡排序
  • 原文地址:https://www.cnblogs.com/WHFF521/p/11592901.html
Copyright © 2011-2022 走看看