无向图满足约束条件的路径
•【目的】:掌握深度优先遍历算法在求解图路径搜索问题的应用
【内容】:编写一个程序,设计相关算法,从无向图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。