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("请输入节点的个数\n");
    scanf("%d", &n);
    printf("请输入已知数据的组数\n");
    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("请输入节点的个数\n");
    scanf("%d", &n);
    printf("请输入已知数据的组数\n");
    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;
}

 

posted on 2015-12-09 17:18  张明明_1  阅读(1265)  评论(1编辑  收藏  举报

导航