ZOJ 1456 / HDOJ 1385 -- Minimum Transport Cost (FLoyd+路径字典序)

之前尝试用 Dijkstra 写,但是回溯部分不会写,无奈之下网上找了一下别人的解题报告,发现竟然是用 Floyd 写的,我接触 Floyd 不太深入,于是在做这道题目的时候,我重新回顾了 Floyd 算法,思考其核心思想

 

预处理:约定 edge 保存输入数据的边权值,tax 保存站点的费用,ss,tt 分别记录当前的 起点 和 终点,那么可以这样构图,对于 ss 和 tt,显然这两点是不需要 tax 的,那么dist 数据记录 ss 到 当前点 k 的总费用,即 dist[ i ][ j ] = edge[ i ][ j ] + tax[ j ] (edge[ i ][ j ]!=0,edge[ i ][ j ]!=INF,j!=ss,j!=tt)

 

代码如下:

View Code
  1 /*
  2 PROG:   Minimum Transport Cost
  3 ID  :   ouyangyewei
  4 LANG:   C++
  5 */
  6 #include <cstdio>
  7 #include <cstdlib>
  8 #include <cstring>
  9 #include <memory.h>
 10 #include <algorithm>
 11 
 12 const int maxn = 36;
 13 const int INF = 0x3F3F3F3F;
 14 
 15 int  N, EndPoint, tax[maxn], edge[maxn][maxn];
 16 int  path[maxn][maxn], dist[maxn][maxn];
 17 
 18 void ReadData()
 19 {
 20     int i, j;
 21     for ( i=1; i<=N; ++i )
 22     {
 23         for ( j=1; j<=N; ++j )
 24             scanf("%d", &edge[i][j]);
 25     }// graph
 26     for ( i=1; i<=N; ++i )
 27         scanf("%d", &tax[i]);
 28 }// ReadData
 29 
 30 void Initalize( int src, int dest )
 31 {
 32     for ( int i=1; i<=N; ++i )
 33     {
 34         for ( int j=1; j<=N; ++j )
 35         {
 36             path[i][j] = j;
 37             if ( j!=src && j!=dest && edge[i][j]!=0 && edge[i][j]!=-1 )
 38                 dist[i][j] = edge[i][j]+tax[j];
 39             else
 40                 dist[i][j] = ( edge[i][j]==-1 ) ? INF:edge[i][j];
 41         }
 42     }// End of for
 43     
 44     /*
 45     for ( int i=1; i<=N; ++i )
 46     {
 47         for ( int j=1; j<=N; ++j )
 48             printf("%10d ", dist[i][j]);
 49         printf("\n");
 50     }
 51     printf("\n");
 52     */
 53     
 54 }// Initalize
 55 
 56 void Floyd( int src )
 57 {
 58     for ( int k=1; k<=N; ++k )
 59     {
 60         for ( int i=1; i<=N; ++i )
 61         {
 62             for ( int j=1; j<=N; ++j )
 63             {
 64                 if ( k==i || k==j )    continue;
 65                 
 66                 int tt = dist[i][k]+dist[k][j];
 67                 if ( tt<dist[i][j] )
 68                     dist[i][j] = tt, path[i][j] = path[i][k];
 69                 else if ( tt==dist[i][j] && path[i][j]>path[i][k] )
 70                     path[i][j] = path[i][k];
 71             }
 72         }
 73     }// Loop
 74 }// Floyd
 75 /*
 76 void dfs( int ss, int tt )
 77 {
 78     if ( tt!=ss )
 79         dfs( ss, path[ss][tt] );
 80     
 81     if ( tt!=EndPoint )
 82         printf("%d-->", tt);
 83 }// dfs
 84 */
 85 void output( int src, int dest )
 86 {
 87     printf("From %d to %d :\nPath: %d", src, dest, src);
 88     
 89     int t = src;
 90     while ( t!=dest )
 91     {
 92         printf("-->%d", path[t][dest]);
 93         t = path[t][dest];
 94     }
 95 
 96     printf("\nTotal cost : %d\n\n", dist[src][dest]);
 97 }// output
 98 
 99 void Solve()
100 {
101     int ss, tt;
102     while ( ~scanf("%d %d", &ss, &tt), ss+tt!=-2 )
103     {
104         Initalize( ss, tt );
105         Floyd( ss );
106         output( ss, tt );
107     }// start point and destination
108 }// Solve
109 
110 int main()
111 {
112     while ( ~scanf("%d", &N), N!=0 )
113     {
114         ReadData();
115         Solve();
116     }// End of while
117     
118     return 0;
119 }

转载于:https://www.cnblogs.com/yewei/archive/2012/08/09/2630867.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值