• HDU 1385 Minimum Transport Cost (floyd算法,求最短路径)


    http://acm.hdu.edu.cn/showproblem.php?pid=1385

    这个是模板题目。

    核心算法:

    通过一个图的权值矩阵求出它的每两点间的最短路径矩阵
    从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。
    采用的是(松弛技术),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);
    其状态转移方程如下: map[i,j]:=min{map[i,k]+map[k,j],map[i,j]}
    map[i,j]表示i到j的最短距离
    K是穷举i,j的断点
    map[n,n]初值应该为0,或者按照题目意思来做。
    当然,如果这条路没有通的话,还必须特殊处理,比如没有map[i,k]这条路
    算法
    1,从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
    2,对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
    ===
    把图用邻接距阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。
    定义一个距阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。
    把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。
    在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。
    算法易于理解及书写,但是时间复杂度太高。
    #include<stdio.h>
    #include<string.h>
    #define MAX 9999999
    int ans[1000][1000],map[1000][1000],tax[1000];
    int vertex;
    int min(int a,int b)
    {
        return a<b?a:b;
    }
    void init()
    {
        int i,j;
        for(i=0;i<vertex;i++)
            for(j=0;j<vertex;j++)
            if(i==j)map[i][j]=0;
            else map[i][j]=MAX;//起点跟终点一致,说明可以0费用,否则就先初始化为最大
    }
    void input()
    {
        int i,x,y,cost,j;
        for(i=0;i<vertex;i++)
            for(j=0;j<vertex;++j)
            {
                scanf("%d",&cost);
                if(cost!=-1)
                    map[i][j]=cost;
                ans[i][j]=j;
            }
        for(i=0;i<vertex;++i)
            scanf("%d",&tax[i]);
    }
    int floyd()
    {
        int i,j,k,sum;
        for(k=0;k<vertex;++k)
            for(i=0;i<vertex;++i)
                for(j=0;j<vertex;++j)
                {
                    sum=map[i][k]+map[k][j]+tax[k];
                    if(sum<map[i][j])
                    {
                        map[i][j]=sum;//如果存在k点使得ij路径可松弛,那么就更新这条路径上的数据
                        ans[i][j]=ans[i][k];//存储该点的前一点
                    }
                    else if(sum==map[i][j])//这里是为了字典序
                    {
                        ans[i][j]=min(ans[i][j],ans[i][k]);
    
                    }
                }
    }
    void print(int start,int end)
    {
        int k,i;
        printf("From %d to %d :
    ",start+1,end+1);
        printf("Path: %d",start+1);
        k=start;
        while(k!=end)//输出路径从起点到终点
        {
            printf("-->%d",ans[k][end]+1);
            k=ans[k][end];
        }
        printf("
    ");
        printf("Total cost : %d
    
    ",map[start][end]);
    }
    
    int main()
    {
        int i,j,start,end;
        while(scanf("%d",&vertex),vertex)
        {
            init();
            input();
            floyd();
            while(scanf("%d%d",&start,&end),start!=-1||end!=-1)
            print(start-1,end-1);//这里一定记得要把点跟下标对齐,即-1
        }
        return 0;
    }
    View Code
  • 相关阅读:
    元组tuple
    列表list
    day11---闭包函数
    day10函数对象,嵌套,名称空间,作用域
    day10函数对象,嵌套,名称空间,作用域
    day--函数
    day8--文件管理2
    day ---7,文件管理
    day7,文件编码
    day6---字典,集合内置方法
  • 原文地址:https://www.cnblogs.com/huzhenbo113/p/3285923.html
Copyright © 2020-2023  润新知