zoukankan      html  css  js  c++  java
  • floyed算法

    Floyed算法(实际是动态规划问题)
      问题:权值矩阵matrix[i][j]表示i到j的距离,如果没有路径则为无穷
         求出权值矩阵中任意两点间的最短距离

      分析:对于每一对定点u,v看是否存在一个点w使从u到w再到v的路径长度比已知路径短
      如果有则更新从u到w的距离
      参考网页
      1:不用状态压缩的动态规划算法:
        状态定义:d[1][i][j]表示以1作为媒介时从i到j的最短距离
             d[2][i][j]表示以1,2中的点作为媒介时从i到j的最短距离
             ……
            d[n][i][j]表示以1,2, ……n中的点作为媒介时从i到j的最短距离

            状态转移方程d[k][i][j] = min(d[k-1][i][j], d[k-1][i][j]+d[k-1][k][j]);

            理解为把i到j的路径氛围两种情况,一种不经过k,一种经过k


      2:状态压缩表示:
        假设用d[i][j]表示从i到j的最短路径
        由于d[i][j]在计算中重复使用,因此表示阶段的那一维被取消了
        在没有计算出来新的d[i][j]的时候d[i][j]存储的实际是d[k-1][i][j]的值
        因此可以省去表示阶段的那一维
        状态转移方程:d[i][j] = min(d[i][j], d[i][j]+d[k][j]);

    int matrix[M][M];
    void floyed_orginal(int n)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
              d[0][i][j] = matrix[i][j];  
        }
        for(int k = 1; k <= n; k++)
        {
            for(int i = 1; i <= n; i++)
            {
                for(int j = 1; j <= n; j++)
                    d[k][i][j] = min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j]);
            }
        }
    }
    void floyd() 
    {
        for(int k = 1; k <= n; k++)
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                    d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    }

     路经压缩之前的floyed算法测试代码

    /*  本程序中节点标号1,2,……n
        floyed算法:
            floyed算法实际上是动态规划,
            对于任意两个点u,v,看是否存在一个点w,使得从u到w再到v的距离比从u直接到v的距离短
    
            d[k][i][j]存储从i到j经过1, 2, ……k,的路径中的最短路径
            比如d[1][i][j]存存储经过1时从i到j的最短距离
                d[2][i][j]存储经过1, 2中的点时时从i到j的最短距离
    
            得到状态转移方程d[k][i][j] = min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j]);
    */
    #define M 100
    #define INF 0x3f3f3f
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    int d[M][M][M];
    int mat[M][M];
    int n, m;
    void FloyedOrginal()                          
    {
        //无论经不经过中间节点,任意两点间的最短距离初始化为无穷
        for(int k = 0; k <= n; k++)
            for(int i = 0; i <= n; i++)
                for(int j = 0; j <= n; j++)
                    d[i][k][k] = INF;
        //不经过中间节点的时候两点间的距离初始化为两点间本身的距离
        for(int i = 1; i <= n; i++)
            for(int j = 1; j <= n; j++)
                d[0][i][j] = mat[i][j];
        //动态规划过程
        for(int k = 1; k <= n; k++)
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                    d[k][i][j] = min(d[k-1][i][j], d[k-1][i][j]+d[k-1][k][j]);
    }
    void Init()
    {
        printf("请输入节点的个数
    ");
        scanf("%d", &n);
        printf("请输入已知数据的组数
    ");
        scanf("%d", &m);
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= n; j++)
                mat[i][j] = INF;
        for(int i = 0; i < m; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            mat[u][v] = mat[v][u] = w;
        }
    }
    int main()
    {
        Init();
        FloyedOrginal();
        printf("%d", d[n][1][n]);
        return 0;
    }

     路径压缩之后

    /*  本程序中节点标号1,2,……n
        floyed算法:
            floyed算法实际上是动态规划,
            对于任意两个点u,v,看是否存在一个点w,使得从u到w再到v的距离比从u直接到v的距离短
    
            d[i][j]存储从i点到j点的最短距离
    */
    #define M 100
    #define INF 0x3f3f3f
    #include <stdio.h>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    int mat[M][M];
    int n, m;
    void FloyedOrginal()
    {
        //用k遍历所有中间节点的可能
        for(int k = 1; k <= n; k++)
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                        mat[i][j] = min(mat[i][j], mat[i][k]+mat[k][j]);//是否经过k
    }
    void Init()
    {
        printf("请输入节点的个数
    ");
        scanf("%d", &n);
        printf("请输入已知数据的组数
    ");
        scanf("%d", &m);
        for(int i = 0; i <= n; i++)
            for(int j = 0; j <= n; j++)
                mat[i][j] = INF;
        for(int i = 0; i < m; i++)
        {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            mat[u][v] = mat[v][u] = w;
        }
    }
    int main()
    {
        Init();
        FloyedOrginal();
        printf("%d", mat[1][4]);
        return 0;
    }
  • 相关阅读:
    GNU make manual 翻译(四十一)
    GNU make manual 翻译(三十五)
    GNU make manual 翻译(三十三)
    GNU make manual 翻译(三十八)
    GNU make manual 翻译(四十二)
    GNU make manual 翻译(三十四)
    艾瑞咨询:即时通讯面临多种安全威胁 狼人:
    世界头号黑客称奥巴马超级加密黑莓手机可被攻破 狼人:
    微软悬赏25万美元捉拿Conficker蠕虫作者 狼人:
    信息周刊:随意设置电脑密码存在安全隐患 狼人:
  • 原文地址:https://www.cnblogs.com/rain-1/p/5033505.html
Copyright © 2011-2022 走看看