杭电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;
}
原文地址:https://www.cnblogs.com/soTired/p/4762993.html