最短路经典算法-dijkstra范例(两道),第一道是裸的dijkstra,第二道需要枚举所有边已找到可能的情况。
ZOJ2750-Idiomatic Phrases Game
题意:见Code
题解:dijkstra算法需要理解的是松弛操作,这一点掌握好了,其他的代码书写则有点类似于Prim算法,易于掌握。
本题需要记录每一个成语的前4个字符和后4个字符以记录成语的第一个字和最后一个字,博主省略了建图的过程,直接重载了Idiom结构体的“==”运算符,在dijkstra也直接使用了该判断,经过分析可以知道这种算法和利用邻接矩阵建图后再进行dijkstra的算法时间度基本一致O(n^2),因此权当简化代码也好。
1 //成语接龙-dijkstra 2 //求从第一个成语道最后一个成语最短耗时(第一个列数据为T,表示需要耗时T后才能接龙下一个成语) 3 //Time:50Ms Memory:292K 4 #include<iostream> 5 #include<cstring> 6 #include<cstdio> 7 #include<vector> 8 #include<algorithm> 9 using namespace std; 10 11 #define MAX 1001 12 #define INF 0x3f3f3f3f 13 14 struct Idiom { 15 int time; 16 char pre[5], rear[5]; 17 friend bool operator == (Idiom id1, Idiom id2) { return !strcmp(id1.rear, id2.pre); } 18 }idiom[MAX]; 19 20 int n; 21 int d[MAX], mintime; //mintime:最短路耗时 22 bool v[MAX]; 23 24 void dijkstra() 25 { 26 memset(v, false, sizeof(v)); 27 memset(d, INF, sizeof(d)); 28 v[0] = true; 29 mintime = -1; //默认失败 30 for (int i = 1; i < n; i++) 31 { 32 if (idiom[0] == idiom[i]) 33 d[i] = idiom[0].time; 34 } 35 for (int i = 1; i < n; i++) 36 { 37 int mind = INF; 38 int k; 39 for (int j = 1; j < n;j++) 40 { 41 if (!v[j] && mind > d[j]) 42 { 43 mind = d[j]; 44 k = j; 45 } 46 } 47 48 if (mind == INF) return; //失败 49 if (k == n - 1) { //成功 50 mintime = d[k]; 51 return; 52 } 53 v[k] = true; 54 for (int j = 1; j < n; j++) 55 if (!v[j] && idiom[k] == idiom[j]) d[j] = min(d[k] + idiom[k].time, d[j]); 56 } 57 } 58 59 int main() 60 { 61 while (scanf("%d", &n), n) 62 { 63 char str[25]; 64 for (int i = 0; i < n; i++) 65 { 66 scanf("%d%s", &idiom[i].time, str); 67 int len = strlen(str); 68 for (int j = 0; j < 4; j++) 69 { 70 idiom[i].pre[j] = str[j]; 71 idiom[i].rear[j] = str[len - 4 + j]; 72 } 73 idiom[i].pre[4] = idiom[i].rear[4] = '