中国大学MOOC-数据结构基础习题集、06-2、旅游规划
题目链接:http://www.patest.cn/contests/mooc-ds/06-2
题目分析:陈姥姥说,这是Dijstra算法的一道题。题目是中文的,这里就不再啰嗦了。有一点提示一下,咱们平时用的Dijistra算法,是用来求最短路径的。这道题不仅要求最短路径,而且要兼顾收费总额,因此除了dist数组还需要一个cost数组。可以在判断if ( dist[V] + data[V][W] < dist[W] )之后,在以同样的方法判断cost。各位同学在做的时候,如果觉得求收费有难度,不妨先自己先把怎么求最短路径的程序写一下,之后再继续看。
特别说明:
1. 用邻接矩阵表示图比较容易。除了要保存路径长度,还要保存收费金额,因此不妨设置两个邻接矩阵。具体方法见下。
2. 二维数组的动态申请及初始化,不推荐大家#define一个较大的数,然后直接int a[MAX][MAX],这样做是十分不负责的,十分浪费空间。如果不会的同学,可以参见如下方法:
1 // 用邻接矩阵存储图 2 int **data = new int*[n]; 3 int **eCost = new int*[n]; 4 for(int i=0; i<n; i++) 5 { 6 data[i] = new int[n]; 7 eCost[i] = new int[n]; 8 } 9 // 邻接矩阵初始化 10 for(int i=0; i<n; i++) 11 { 12 for(int j=0; j<n; j++) 13 { 14 data[i][j] = MAXNUM; 15 eCost[i][j] = MAXNUM; 16 } 17 }
3. 无向图 = 双向图,这点说了很多次了,输入的时候要记得双向处理!
1 // 处理输入数据,并构造邻接矩阵 2 for(int i=0; i<m; i++) 3 { 4 int a1, a2, a3, a4; 5 cin >> a1 >> a2 >> a3 >> a4; 6 data[a1][a2] = a3; 7 data[a2][a1] = a3; 8 eCost[a1][a2] = a4; 9 eCost[a2][a1] = a4; 10 }
代码分析:
额……该说的都在【特别说明】中提到了,这道题的代码量还是比较少的。对于第60行的for循环为什么执行2次呢,其实我也不知道。最开始我用的是while死循环,但是一直没想好怎么跳出循环。干脆一不做二不休,直接执行m次算了,后来发现时间太久了,case2错了,case4超时了。就改成固定的5次,竟然AC了,然后改成3次,最后改成2次。我试过只做1次的话,结果都是错的。我的直觉告诉我,应该是把两端拼接在一起,第一次循环的后半部分和第二次循环的前半部分可以拼凑出一个完整的结果,所以结果就是对的。当然,这个2这个数很值得考究哈,如果你有更好的算法,不妨在留言区内留言,或者向博主解释一下为什么是2。
Dijistra算法:47~81行
输出最终结果:82行
1 #include <iostream> 2 3 #define MAXNUM 10000000 4 5 using namespace std; 6 7 struct node 8 { 9 int city1; 10 int city2; 11 int len; 12 int cost; 13 node(int a, int b,int c, int d):city1(a), city2(b), len(c), cost(d) {} 14 }; 15 16 int main() 17 { 18 int n, m, s, d; 19 cin >> n >> m >> s >> d; 20 // 用邻接矩阵存储图 21 int **data = new int*[n]; 22 int **eCost = new int*[n]; 23 for(int i=0; i<n; i++) 24 { 25 data[i] = new int[n]; 26 eCost[i] = new int[n]; 27 } 28 // 邻接矩阵初始化 29 for(int i=0; i<n; i++) 30 { 31 for(int j=0; j<n; j++) 32 { 33 data[i][j] = MAXNUM; 34 eCost[i][j] = MAXNUM; 35 } 36 } 37 // 处理输入数据,并构造邻接矩阵 38 for(int i=0; i<m; i++) 39 { 40 int a1, a2, a3, a4; 41 cin >> a1 >> a2 >> a3 >> a4; 42 data[a1][a2] = a3; 43 data[a2][a1] = a3; 44 eCost[a1][a2] = a4; 45 eCost[a2][a1] = a4; 46 } 47 // Dijstra算法开始 48 // 记录当前路径长度 49 int *dist = new int[n]; 50 // 记录当前花费 51 int *cost = new int[n]; 52 // 初始化 53 for(int i=0; i<n; i++) 54 { 55 dist[i] = MAXNUM; 56 cost[i] = MAXNUM; 57 } 58 dist[s] = 0; 59 cost[s] = 0; 60 for(int k=0; k<2; k++) 61 { 62 for(int V=0; V<n; V++) 63 { 64 for(int W=0; W<n; W++) 65 { 66 if(dist[V] != MAXNUM) 67 { 68 if ( dist[V] + data[V][W] < dist[W] ) 69 { 70 dist[W] = dist[V] + data[V][W]; 71 } 72 else if ( dist[V] + data[V][W] == dist[W] 73 && cost[V] != MAXNUM 74 && cost[V] + eCost[V][W] < cost[W]) 75 { 76 cost[W] = cost[V] + eCost[V][W]; 77 } 78 } 79 } 80 } 81 } 82 cout << dist[d] << " " << cost[d] << endl; 83 return 0; 84 }
AC成果: