最短路 + 记录路径 之 zoj 1456 Minimum Transport Cost (hdu 1385)

/*
考虑到测试数据中需要求解任意两点间的最短路,所以采用Floyd-Warshall算法
 
dp[i][j] = min(dp[i][k] + dp[k][j] + tax[k], dp[i][j]);
 
关键在于记录路径,并且要保证:if there are more minimal paths, output the lexically smallest one.
分两种情况讨论:
	(1)dp[i][j] > dp[i][k] + dp[k][j] + tax[k]
		直接更新dp[i][j],保证获得最短路
	(2)dp[i][j] == dp[i][k] + dp[k][j] + tax[k]
		看i节点的直接后继节点编号哪个更小,哪个小选哪个,保证获得 the lexically smallest one。
 
为记录路径:
	path[i][j] := 在节点i到节点j的最短路径上,i的直接后继节点编号。
	初始值:path[i][j] = j
	用这种办法可以记录路径的原因:
		有n个节点,从1->n的最短路径,假设是这样的1->2->3->4->...->n,则2->n的最短路径
		必然是2->3->4->...->n,3->n的最短路径必然是3->4->...->n,如果不是这样的,那么
		当前1->n的路径必然不是1->n的最短路径,与假设矛盾。
	通过循环即可获得1->n的完整最短路径。
*/
  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstddef>
  5 #include <iterator>
  6 #include <algorithm>
  7 #include <string>
  8 #include <locale>
  9 #include <cmath>
 10 #include <vector>
 11 #include <cstring>
 12 #include <map>
 13 #include <utility>
 14 #include <queue>
 15 #include <stack>
 16 #include <set>
 17 using namespace std;
 18 const int INF = 0x3f3f3f3f;
 19 const int MaxN = 205;
 20 const int modPrime = 3046721;
 21 
 22 int N;
 23 int dp[MaxN][MaxN];
 24 int tax[MaxN];
 25 int path[MaxN][MaxN];
 26 
 27 
 28 void Solve()
 29 {
 30     for (int i = 0; i < N; ++i)
 31     {
 32         for (int j = 0; j < N; ++j)
 33         {
 34             path[i][j] = j;
 35         }
 36     }
 37     for (int k = 0; k < N; ++k)
 38     {
 39         for (int i = 0; i < N; ++i)
 40         {
 41             for (int j = 0; j < N; ++j)
 42             {
 43                 //dp[i][j] = min(dp[i][k] + dp[k][j] + tax[k], dp[i][j]);
 44                 if (dp[i][j] > dp[i][k] + dp[k][j] + tax[k])
 45                 {
 46                     dp[i][j] = dp[i][k] + dp[k][j] + tax[k];
 47                     path[i][j] = path[i][k];
 48                 }
 49                 else
 50                 {
 51                     if (dp[i][j] == dp[i][k] + dp[k][j] + tax[k])
 52                     {
 53                         if (path[i][j] > path[i][k])
 54                         {
 55                             path[i][j] = path[i][k];
 56                         }
 57                     }
 58                 }
 59             }
 60         }
 61     }
 62 
 63     int src, dsn;
 64     while ((~scanf("%d %d", &src, &dsn)) && !(src == -1 && dsn == -1))
 65     {
 66         printf("From %d to %d :\n", src, dsn);
 67         printf("Path: "); 
 68         int tmp = src - 1;
 69         printf("%d", src);
 70         while (tmp != dsn - 1)
 71         {
 72             printf("-->");
 73             printf("%d", path[tmp][dsn - 1] + 1);
 74             tmp = path[tmp][dsn - 1];
 75         }
 76         
 77 
 78         printf("\n");
 79         printf("Total cost : %d\n\n", dp[src - 1][dsn - 1]);
 80     }
 81 }
 82 
 83 int main()
 84 {
 85 #ifdef HOME
 86     freopen("in", "r", stdin);
 87     //freopen("out", "w", stdout);
 88 #endif
 89 
 90     while (~scanf("%d", &N) && N)
 91     {
 92         for (int i = 0; i < N; ++i)
 93         {
 94             for (int j = 0; j < N; ++j)
 95             {
 96                 scanf("%d", &dp[i][j]);
 97                 if (dp[i][j] == -1)
 98                 {
 99                     dp[i][j] = INF;
100                 }
101             }
102         }
103         for (int i = 0; i < N; ++i)
104         {
105             scanf("%d", &tax[i]);
106         }
107         Solve();
108     }
109 
110 
111 #ifdef HOME
112     cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl;
113     _CrtDumpMemoryLeaks();
114 #endif
115     return 0;
116 }
 
 

 

 

转载于:https://www.cnblogs.com/shijianming/p/5025609.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值