标签:
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
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
题意:n座城市,出租车经过编号为i城市要交的费用是cost[i],给出n*n的邻接矩阵,求多对从s到e的最小花费,并按字典序打印路径。
解析:由于有多对起始点,所以用Floyd算法。但是要稍微处理一下,每次松弛操作的判断条件要改一下,因为总费用要加上出租车经过城市的费用。对于记录字典序最小路径,也是在Floyd里面判断两路径相同时,取字典序小的地点。注意path[i][j]里面保存的是i到j路径上的经过的第一个点,输出的时候,只需要一直回溯输出即可。详见代码
AC代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define INF 1e7 + 2 int n, m; int d[202][202], v[202]; int cost[202]; int path[202][202]; void floyd(){ for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) path[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 temp = d[i][k] + d[k][j] + cost[k]; //加上cost[k] if(d[i][j] > temp){ d[i][j] = temp; path[i][j] = path[i][k]; } else if(d[i][j] == temp){ if(path[i][j] > path[i][k]) //取字典序小的 path[i][j] = path[i][k]; } } } void print(int s, int e){ //打印路径 printf("%d", s); while(e != s){ printf("-->%d", path[s][e]); s = path[s][e]; } puts(""); } int main(){ #ifdef sxk freopen("in.txt", "r", stdin); #endif //sxk int x, y, z, s , t; while(scanf("%d", &n)!=EOF && n){ for(int i=1; i<=n; i++) for(int j=1; j<=n; j++){ scanf("%d", &d[i][j]); if(d[i][j] == -1) d[i][j] = INF; } for(int i=1; i<=n; i++) scanf("%d", &cost[i]); floyd(); for(int i=0; ; i++){ scanf("%d%d", &x, &y); if(x == -1 && y == -1) break; printf("From %d to %d :\n", x, y); printf("Path: "); print(x, y); printf("Total cost : %d\n", d[x][y]); puts(""); } } return 0; }
PS:真的学习了,第一次写Floyd的打印路径,还是按字典序,真是太神奇了~~~
hdu 1385 Minimum Transport Cost (Floyd + 字典序打印路径)
标签:
原文地址:http://blog.csdn.net/u013446688/article/details/42967457