• 杭电1385--Minimum Transport Cost(Floyd字典序打印路径)


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

    Input
    First is N, number of cities. N = 0 indicates the end of input.

    The data of path cost, city tax, source and destination cities are given in the input, which is of the form:

    a11 a12 ... a1N
    a21 a22 ... a2N
    ...............
    aN1 aN2 ... aNN
    b1 b2 ... bN

    c d
    e f
    ...
    g h

    where aij is the transport cost from city i to city j, aij = -1 indicates there is no direct path between city i and city j. bi represents the tax of passing through city i. And the cargo is to be delivered from city c to city d, city e to city f, ..., and g = h = -1. You must output the sequence of cities passed by and the total cost which is of the form:
     
    Output
    From c to d :
    Path: c-->c1-->......-->ck-->d
    Total cost : ......
    ......

    From e to f :
    Path: e-->e1-->..........-->ek-->f
    Total cost : ......

    Note: if there are more minimal paths, output the lexically smallest one. Print a blank line after each test case.

     
    Sample Input
    5 0 3 22 -1 4 3 0 5 -1 -1 22 5 0 9 20 -1 -1 9 0 4 4 -1 20 4 0 5 17 8 3 1 1 3 3 5 2 4 -1 -1 0
     
    Sample Output
    From 1 to 3 :
    Path: 1-->5-->4-->3
    Total cost : 21
     
    From 3 to 5 :
    Path: 3-->4-->5
    Total cost : 16
     
    From 2 to 4 :
    Path: 2-->1-->5-->4
    Total cost : 17
     
    Source
     
    Recommend
    Eddy   |   We have carefully selected several similar problems for you:  1142 1548 1690 2722 1598 
     
    一上午也没干啥, 就看这道题了, 也确实发现最短路白学了, 水平仅限于敲模板。但更说明一个问题, 我要Fighting!! 题目要打印路径、 输出最少费用(过路费和运费)。
    ac码:
    //Floyd更新最短路时用到了动规思想, 
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    int map[100][100], Tax[100], Result[100][100];  //Result 记录路径; 
    int n;
    void Floyd()
    {
        for(int i = 1; i <= n; i++)  //初始化为列; 
            for(int j = 1; j <= n; j++)    
                Result[i][j] = j;
        for(int k = 1; k <= n; k++)    
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                {
                    int Q = map[i][k] + map[k][j] + Tax[k];  
                    if(map[i][j] > Q)
                    {
                        map[i][j] = Q;
                        Result[i][j] = Result[i][k];   //更新路径; 
                    } 
                    if(map[i][j] == Q)
                    {
                        if(Result[i][j] > Result[i][k])
                        Result[i][j] = Result[i][k];  //字典序; 
                    }
                }
    }
    int main()
    {
        while(~scanf("%d", &n), n)
        {
            int M, j = 0;
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                {
                    scanf("%d", &M);
                    if(M == -1)
                        map[i][j] = INF;
                    else
                        map[i][j] = M;    
                }
            for(int i = 1; i <= n; i++)
                scanf("%d", &Tax[i]);
            Floyd(); 
            int a, b;
            while(~scanf("%d %d", &a, &b))
            {
                if(j != 0)
                    printf("
    ");
                if(a == -1 && b == -1)
                    break;
                printf("From %d to %d :
    ", a, b);
                printf("Path: %d", a);
                int t = a;
                while(t != b)
                {
                    printf("-->%d", Result[t][b]);
                    t = Result[t][b];
                }    
                j++;
                printf("
    Total cost : %d
    ", map[a][b]);
            }
            //printf("
    ");
        }
        return 0;
    }

    思路是对的:

    //但为啥一直TLE, 数组都换成x[10][10]了还是不行; 
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int INF = 0x3f3f3f3f;
    int Map[10][10], map[10][10];
    int dis[10], vis[10], pre[10], Tax[10], Result[10];
    int n;
    void Dijkstra(int src)
    {
    //    memset(pre, -1, sizeof(pre));
        memset(vis, 0, sizeof(vis));
        for(int i = 1; i <= n; i++)
        {
            dis[i] = map[src][i];
            if(dis[i] != INF)
                pre[i] = src;   //记录前驱; 
            else
                pre[i] = 0;
        }
        vis[src] = 1;
        for(int i = 1; i < n; i++)
        {
            int temp = src, min = INF;
            for(int j = 1; j <= n; j++)
            {
                if(!vis[j] && dis[j] < min)
                {
                    temp = j;
                    min = dis[j];    
                }    
            } 
            vis[temp] = 1;
            for(int j = 1; j <= n; j++)
            
                if(!vis[j] && map[temp][j] < INF)
                {
                     if(dis[j] > dis[temp] + map[temp][j]) 
                    {
                        dis[j] = dis[temp] + map[temp][j];
                            pre[j] = temp;   //更新
                    }
                    else if(dis[j] == dis[temp] + map[temp][j])
                    {
                        if(pre[j] > temp)
                            pre[j] = temp;    //更新前驱; 
                    } 
                }
        }
    
    }
    int main()
    {
        while(~scanf("%d", &n), n)
        {
            for(int i = 1; i <= n; i++)
                for(int j = 1; j <= n; j++)
                {
                    cin >> Map[i][j];
                    if(Map[i][j] == -1 || !Map[i][j])
                        Map[i][j] = INF;    
                }    
            for(int i = 1; i <= n; i++)
                scanf("%d", &Tax[i]); 
            int a, b;
            while(~scanf("%d %d", &a, &b))
            {
                if(a == -1 && b == -1)
                    break;
                int Q = 0;
                for(int i = 1; i <= n; i++)
                    for(int j = 1; j <= n; j++)
                    {
                        if(j == a || j == b)
                            map[i][j] = Map[i][j];
                        else
                            map[i][j] = Map[i][j] + Tax[j];    
                    }    
                Dijkstra(a);
                int t = pre[b];
                while(t != a)           //数组模拟回溯过程;  
                {
                    Result[Q++] = t; 
                    t = pre[t];
                }
                printf("From %d to %d :
    ", a, b); 
                printf("Path: %d", a);
                for(int I = Q -1; I >= 0; I--)
                    printf("-->%d", Result[I]); //It's cool 
                printf("-->%d
    ", b);
                printf("Total cost : %d
    ", dis[b]);
                printf("
    ");
            } 
        } 
        return 0;
    }
  • 相关阅读:
    vagrant中配置多虚拟机
    更改centos的hostname
    静态变量设为nonpublic或者加final关键字
    随机数Random和SecureRandom
    C#技术栈入门到精通系列18——映射框架AutoMapper
    C#技术栈入门到精通系列13——日志框架Log4Net
    MFC 弹出窗口初始化
    MFC ListControl 智障总结
    Windows本地磁盘无法重命名
    C++ private类访问
  • 原文地址:https://www.cnblogs.com/soTired/p/4762993.html
Copyright © 2020-2023  润新知