标签:
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