用图搜索方法求解迷宫问题

/**
*    实验题目:
*        用图搜索方法求解迷宫问题
*    实验目的:
*        深入掌握图遍历算法在求解实际问题中的应用。
*    实验内容:
*        编写一个程序,完成如下功能:
*    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)

  • 6
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用 Python 实现的横向搜索算法来解决迷宫问题: ```python from collections import deque def find_path(maze): # 迷宫的行列数 rows, cols = len(maze), len(maze[0]) # 起点和终点 start, end = (0, 0), (0, 0) # 找到起点和终点 for i in range(rows): for j in range(cols): if maze[i][j] == 0: if start == (0, 0): start = (i, j) else: end = (i, j) # 使用队列来保存待搜索的节点,每个节点包括坐标和路径 queue = deque([(start, [start])]) # 使用 visited 集合来保存已经搜索过的节点 visited = set([start]) # 开始搜索 while queue: current, path = queue.popleft() x, y = current # 如果到达终点,返回路径 if current == end: return path # 尝试向上、下、左、右四个方向走 for dx, dy in [(0, 1), (0, -1), (1, 0), (-1, 0)]: new_x, new_y = x + dx, y + dy if 0 <= new_x < rows and 0 <= new_y < cols and maze[new_x][new_y] == 0 and (new_x, new_y) not in visited: queue.append(((new_x, new_y), path + [(new_x, new_y)])) visited.add((new_x, new_y)) # 如果搜索完整个图都没有找到路径,返回空列表 return [] ``` 在上述代码中,我们使用 BFS(广度优先搜索)算法来搜索迷宫的所有路径。我们首先找到起点和终点,并将起点加入队列中。然后,我们从队列中取出第一个节点,尝试向上、下、左、右四个方向走,并将新的节点加入队列中。如果新的节点是终点,我们就找到了一条路径,直接返回该路径。 如果搜索完整个图都没有找到路径,我们将返回一个空列表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值