/**
* 实验题目:
* 用图搜索方法求解迷宫问题
* 实验目的:
* 深入掌握图遍历算法在求解实际问题中的应用。
* 实验内容:
* 编写一个程序,完成如下功能:
* 1、建立一个迷宫对应的邻接表表示。
* 2、采用深度优先遍历算法输出从入口(1,1)到出口(M,N)的所有迷宫路径。
* 本实验采用深度优先遍历算法求所有迷宫路径。在用图搜索方法求解迷宫
* 问题时,一个方块看成是一个顶点,其编号为(i,j)。为此相应地修改图的
* 邻接表,邻接表的表头数组改为一个二维数组adjlist,其元素adjlist[i][j]
* 仅含有一个firstarc指针,它指向方块(i,j)的四周可走方块构成的一个单链表。
*
*/
#include <stdio.h>
#include <malloc.h>
#define MAX_SIZE 100
#define M 4 // 行数
#define N 4 // 列数
/*----------------------------以下定义邻接表类型---------------------------*/
typedef struct ANode // 边的结点结构类型
{
int i, j; // 该边的终点位置(i,j)
struct ANode *nextarc; // 指向下一条边的指针
}ArcNode;
typedef struct Vnode // 邻接表头结点的类型
{
ArcNode *firstarc; // 指向第一个相邻点
}VNode;
typedef struct
{
VNode adjlist[M + 2][N + 2]; // 邻接表头结点数组
}ALGraph; // 图的邻接表类型
typedef struct
{
int i; // 当前方块的行号
int j; // 当前方块的列号
}Box;
typedef struct
{
Box data[MAX_SIZE];
int length; // 路径长度
}PathType; // 定义路径类型
int cnt = 0;
int visited[M + 2][N + 2] = {0};
/*-------------------由迷宫数组mg建立对应的邻接表G--------------------*/
static void CreateAdj(ALGraph *&G, int mg[][N + 2])
{
int i, j;
int di;
int i1, j1;
ArcNode *p;
G = (ALGraph *)malloc(sizeof(ALGraph));
for(i = 0; i < M + 2; i++) // 给邻接表中所有头结点的指针域设置初值
{
for(j = 0; j < N + 2; j++)
{
G->adjlist[i][j].firstarc = NULL;
}
}
for(i = 1; i <= M; i++) // 检查mg中每个元素
{
for(j = 1; j <= N; j++)
{
if(mg[i][j] == 0)
{
di = 0;
while(di < 4)
{
switch(di)
{
case 0: // 向上走
i1 = i - 1;
j1 = j;
break;
case 1: // 向右走
i1 = i;
j1 = j + 1;
break;
case 2: // 向下走
i1 = i + 1;
j1 = j;
break;
case 3: // 向左走
i1 = i;
j1 = j - 1;
break;
}
if(mg[i1][j1] == 0) // (i1,j1)为可走方块
{
p = (ArcNode *)malloc(sizeof(ArcNode)); // 创建一个结点p
p->i = i1;
p->j = j1;
p->nextarc = G->adjlist[i][j].firstarc; // 将p结点链到链表后
G->adjlist[i][j].firstarc = p;
}
di++;
}
}
}
}
}
/*-----------------------输出邻接表G--------------------------*/
static void DispAdj(ALGraph *G)
{
int i, j;
ArcNode *p;
for(i = 0; i < M + 2; i++)
{
for(j = 0; j < N + 2; j++)
{
printf(" [%d,%d]: ", i, j);
p = G->adjlist[i][j].firstarc;
while(p != NULL)
{
printf("(%d,%d)", p->i, p->j);
p = p->nextarc;
}
printf("\n");
}
}
}
/*---------------------销毁邻接表--------------------------*/
static void DestroyAdj(ALGraph *&G)
{
int i, j;
ArcNode *pre, *p;
for(i = 0; i < M + 2; i++)
{
for(j = 0; j < N + 2; j++)
{
pre = G->adjlist[i][j].firstarc;
if(pre != NULL)
{
p = pre->nextarc;
while(p != NULL)
{
free(pre);
pre = p;
p = p->nextarc;
}
free(pre);
}
}
}
free(G);
}
/*--------------在图G中采用DFS算法求(xi,yi)到(xe,ye)的所有路径-------------*/
// path数组记录访问过的顶点序列,当找到出口时输出path中的访问序列
static void FindPath(ALGraph *G, int xi, int yi, int xe, int ye, PathType path)
{
ArcNode *p;
visited[xi][yi] = 1; // 置已访问标记
path.data[path.length].i = xi; // 设置起始方块的行号
path.data[path.length].j = yi; // 设置起始方块的列号
path.length++;
if((xi == xe) && (yi == ye)) // 走到迷宫的出口(M,N)时,输出迷宫路径
{
printf(" 迷宫路径%d: ", ++cnt);
for(int k = 0; k < path.length; k++)
{
printf("(%d,%d)", path.data[k].i, path.data[k].j); // 输出迷宫的行号和列号
}
printf("\n");
}
p = G->adjlist[xi][yi].firstarc;
while(p != NULL)
{
if(visited[p->i][p->j] == 0) // 若(p->i,p->j)方块未访问,则递归访问它
FindPath(G, p->i, p->j, xe, ye, path);
p = p->nextarc;
}
visited[xi][yi] = 0; // 取消访问标记
}
int main(void)
{
ALGraph *G;
int mg[M + 2][N + 2] = { // 一个迷宫:其四周加上均为1的外框
{1, 1, 1, 1, 1, 1}, {1, 0, 0, 0, 1, 1},
{1, 0, 1, 0, 0, 1}, {1, 0, 0, 0, 1, 1},
{1, 1, 0, 0, 0, 1}, {1, 1, 1, 1, 1, 1}
};
CreateAdj(G, mg);
printf("迷宫对应的邻接表:\n");
DispAdj(G); // 输出邻接表
PathType path;
path.length = 0;
printf("所有的迷宫路径:\n");
FindPath(G, 1, 1, M, N, path);
DestroyAdj(G);
return 0;
}
测试结果:
迷宫对应的邻接表:
[0,0]:
[0,1]:
[0,2]:
[0,3]:
[0,4]:
[0,5]:
[1,0]:
[1,1]: (2,1)(1,2)
[1,2]: (1,1)(1,3)
[1,3]: (1,2)(2,3)
[1,4]:
[1,5]:
[2,0]:
[2,1]: (3,1)(1,1)
[2,2]:
[2,3]: (3,3)(2,4)(1,3)
[2,4]: (2,3)
[2,5]:
[3,0]:
[3,1]: (3,2)(2,1)
[3,2]: (3,1)(4,2)(3,3)
[3,3]: (3,2)(4,3)(2,3)
[3,4]:
[3,5]:
[4,0]:
[4,1]:
[4,2]: (4,3)(3,2)
[4,3]: (4,2)(4,4)(3,3)
[4,4]: (4,3)
[4,5]:
[5,0]:
[5,1]:
[5,2]:
[5,3]:
[5,4]:
[5,5]:
所有的迷宫路径:
迷宫路径1: (1,1)(2,1)(3,1)(3,2)(4,2)(4,3)(4,4)
迷宫路径2: (1,1)(2,1)(3,1)(3,2)(3,3)(4,3)(4,4)
迷宫路径3: (1,1)(1,2)(1,3)(2,3)(3,3)(3,2)(4,2)(4,3)(4,4)
迷宫路径4: (1,1)(1,2)(1,3)(2,3)(3,3)(4,3)(4,4)