無向圖滿足約束條件的路徑
•【目的】:掌握深度優先遍歷算法在求解圖路徑搜索問題的應用
【內容】:編寫一個程序,設計相關算法,從無向圖G中找出滿足如下條件的所有路徑:
(1)給定起點u和終點v。
(2)給定一組必經點,即輸出的路徑必須包含這些點。
(3)給定一組必避點,即輸出的路徑必須不能包含這些點。
【來源】:《數據結構教程(第五版)》李春葆著,圖實驗11。
代碼:
1 #include<stdio.h> 2 #include<malloc.h> 3 #define MAXV 20 4 typedef struct ANode 5 { 6 int adjvex; 7 struct ANode *nextarc; 8 } ArcNode; 9 10 typedef struct 11 { 12 ArcNode *adjlist[MAXV]; 13 int n1, e1; 14 } AdjGraph; 15 16 int visited[MAXV]; 17 int v1[MAXV], v2[MAXV], n, m; // v1為必過點集合, v2為必避點集合;n為必過點的個數, m為必避點個數 18 int count = 0; //路徑個數 19 20 void CreateAdj(AdjGraph *&G, int A[MAXV][MAXV], int n1, int e1) 21 { 22 int i, j; 23 ArcNode *p; 24 G = (AdjGraph*)malloc(sizeof(AdjGraph)); 25 for (i = 0; i < n1; ++i) 26 G->adjlist[i] = NULL; 27 for (i = 0; i < n1; ++i) 28 for (j = n1; j >= 0; --j) 29 if (A[i][j] == 1) 30 { 31 p = (ArcNode*)malloc(sizeof(ArcNode)); 32 p->adjvex = j; 33 p->nextarc = G->adjlist[i]; 34 G->adjlist[i] = p; 35 } 36 G->n1 = n1; 37 G->e1 = e1; 38 } 39 40 bool comp(int path[MAXV], int d) 41 { 42 int flag1 = 0, f1, flag2 = 0, f2, j; 43 for (int i = 0; i < n; ++i) 44 { 45 f1 = 1; 46 for (j = 0; j <= d; ++j) 47 if (path[j] == v1[i]) 48 { 49 f1 = 0; 50 break; 51 } 52 flag1 += f1; 53 } 54 55 for (int i = 0; i < m; ++i) 56 { 57 f2 = 0; 58 for (j = 0; j <= d; ++j) 59 if (path[j] == v2[i]) 60 { 61 f2 = 1; 62 break; 63 } 64 flag2 += f2; 65 } 66 67 if (flag1 == 0 && flag2 == 0) 68 return true; 69 else 70 return false; 71 } 72 73 void findpath(AdjGraph *G, int u, int v, int d, int path[MAXV]) 74 { 75 int i; 76 ArcNode *p; 77 visited[u] = 1; 78 ++d; path[d] = u; 79 if (u == v && comp(path, d)) 80 { 81 printf("路徑%d:", ++count); 82 printf("%d", path[0]); 83 for (i = 1; i <= d; ++i) 84 printf("->%d ", path[i]); 85 printf("\n"); 86 } 87 p = G->adjlist[u]; 88 while (p != NULL) 89 { 90 if (visited[p->adjvex] == 0) 91 findpath(G, p->adjvex, v, d, path); 92 p = p->nextarc; 93 } 94 visited[u] = 0; 95 } 96 97 int main() 98 { 99 AdjGraph *G; 100 int u, v; // u為起點,v為終點 101 int path[MAXV]; 102 int A[MAXV][MAXV] = { 103 {0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 104 {1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0 }, 105 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, 106 {1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, 107 {1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, 108 {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, 109 {0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 }, 110 {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0 }, 111 {0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, 112 {0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0 }, 113 {0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0 }, 114 {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0 }, 115 {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1 }, 116 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1 }, 117 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 } }; 118 CreateAdj(G, A, 15, 21); 119 printf("輸入起點和終點:"); 120 scanf("%d %d", &u, &v); 121 printf("輸入必過點個數: "); 122 scanf("%d", &n); 123 printf("輸入必過點集合:"); 124 for (int i = 0; i < n; ++i) 125 scanf("%d", &v1[i]); 126 printf("輸入必避點個數: "); 127 scanf("%d", &m); 128 printf("輸入必過點集合:"); 129 for (int i = 0; i < m; ++i) 130 scanf("%d", &v2[i]); 131 printf("\n\n所有探寶路徑如下:\n"); 132 findpath(G, u, v, -1, path); 133 return 0; 134 }
運行結果:
用圖搜索方法求解迷宮問題
•【目的】:深入掌握圖遍歷算法在求解實際問題中的運用
【內容】:編寫一個程序,完成如下功能:
(1) 建立迷宮對應的鄰接表
(2) 采用深度優先遍歷算法輸出從入口(1, 1)到出口(M,N)的所有迷宮路徑
【來源】:《數據結構教程(第五版)》李春葆著,圖實驗14。
代碼:
1 #include<stdio.h> 2 #include<malloc.h> 3 #define MAXV 20 4 #define N 4 5 #define M 4 6 typedef struct ANode 7 { 8 int i, j; // i為橫坐標, j為縱坐標 9 struct ANode *nextarc; 10 } ArcNode; 11 12 typedef struct 13 { 14 ArcNode *mg[N + 2][M + 2]; 15 } AdjGraph; 16 17 typedef struct 18 { 19 int i; 20 int j; 21 } Box; 22 23 typedef struct 24 { 25 Box data[MAXV]; 26 int length; 27 } Path; 28 29 int visited[N + 2][M + 2] = { 0 }; 30 31 void CreateAdj(AdjGraph *&G, int A[N + 2][M + 2], int n, int m) 32 { 33 int i, j, k, i1, j1; 34 ArcNode *p; 35 G = (AdjGraph *)malloc(sizeof(AdjGraph)); 36 for (i = 0; i < n + 2; ++i) 37 for (j = 0; j < m + 2; ++j) 38 G->mg[i][j] = NULL; 39 for (i = 1; i <= n; ++i) 40 for (j = 1; j <= m; ++j) 41 if (A[i][j] == 1) 42 { 43 k = 1; 44 while (k <= 4) 45 { 46 switch (k) 47 { 48 case 1: i1 = i - 1; j1 = j; break; 49 case 2: i1 = i; j1 = j + 1; break; 50 case 3: i1 = i + 1; j1 = j; break; 51 case 4: i1 = i; j = j - 1; break; 52 } 53 ++k; 54 if (A[i1][j1] == 1) 55 { 56 p = (ArcNode*)malloc(sizeof(ArcNode)); 57 p->i = i1; 58 p->j = j1; 59 p->nextarc = G->mg[i][j]; 60 G->mg[i][j] = p; 61 } 62 } 63 } 64 } 65 66 void findpath(AdjGraph *G, int x1, int y1, int xe, int ye, Path pa) 67 { 68 ArcNode *p; 69 ++pa.length; 70 pa.data[pa.length].i = x1; 71 pa.data[pa.length].j = y1; 72 visited[x1][y1] = 1; 73 if (xe == x1 && ye == y1) 74 { 75 for (int u = 0; u <= pa.length; ++u) 76 printf(" (%d, %d) ", pa.data[u].i, pa.data[u].j); 77 } 78 79 p = G->mg[x1][y1]; 80 while (p != NULL) 81 { 82 83 if (visited[p->i][p->j] == 0) 84 findpath(G, p->i, p->j, N, M, pa); 85 p = p->nextarc; 86 } 87 visited[x1][y1] = 0; 88 } 89 90 int main() 91 { 92 AdjGraph *G; 93 Path pa; 94 int A[N + 2][M + 2] = { 95 { 0, 0, 0, 0, 0, 0 },{ 0, 1, 1, 1, 0, 0 }, 96 { 0, 1, 0, 1, 1, 0 },{ 0, 1, 1, 1, 0, 0 }, 97 { 0, 0, 1, 1, 1, 0 },{ 0, 0, 0, 0, 0, 0 } }; 98 CreateAdj(G, A, N, M); 99 pa.length = -1; 100 findpath(G, 1, 1, N, M, pa); 101 return 0; 102 }
求解兩個動物之間通信最少翻譯問題
•【目的】:掌握廣度優先遍歷算法在求解實際問題中的運用
【內容】:編寫一個程序,完成如下功能:
據美國動物分類學家歐內斯特-邁爾推算,世界上有超過100萬種動物,各種動物有自己的語言。假設動物A只能與動物B通信,所以,動物A、C之間通信需要動物B來當翻譯。問兩個動物之間項目通信至少需要多少個翻譯。
測試文本文件test.txt中第一行包含兩個整數n(2<= n <= 200)、m(1 <= m <= 300),其中n代表動物的數量,動物編號從0開始,n個動物編號為0 ~ n-1,m表示可以相互通信動物數,接下來的m行中包含兩個數字分別代表兩種動物可以相互通信,在接下來包含一個整數k(k <= 20),代表查詢的數量,每個查詢,輸出這兩個動物彼此同喜至少需要多少個翻譯,若它們之間無法通過翻譯來通信,輸出-1.
輸入樣本 輸出結果 3 2 0 0 1 1 2 0 0 0 2
【來源】:《數據結構教程(第五版)》李春葆著,圖實驗12。