首页 > 其他分享 >迷宫问题详解(DFS)(谁都能学会版)

迷宫问题详解(DFS)(谁都能学会版)

时间:2025-01-15 12:31:27浏览次数:3  
标签:tmp return fx 迷宫 direct DFS int 详解 pTop

迷宫问题

迷宫问题详解(DFS)

前言:

希望在观看此片之前先去观看懒猫老师的视频,此篇是完全基于课程上的思想和方法来写的,这里直接给大家贴上地址:
https://www.bilibili.com/video/BV1oE41177wk/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=3daecc9000cbc58a3bc39bf941c4d208

对于迷宫算法 在这之前我们需要掌握二维数组,栈的相关知识,嵌套结构体,类等,从名字可以看出就是走迷宫的问题,那么我们就需要定义一个说明方向的二维数组,来说明我们该怎么移动,还需要定义一个数组,来记录我们每一次移动的时的坐标和方向,将每一个数组看成一个元素存储在我们的栈中,然后再逆序遍历栈中元素,就可以得到走出迷宫的正确路线,这只是大致的框架,具体里面的细节非常多,需要我们仔细思考调试来实现完整代码
在这里插入图片描述
由于具体代码较长,我们来分步骤分解这个问题:

具体过程

1.定义方向数组并使用嵌套结构体定义栈中元素

在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>
typedef struct {
    int incX;
    int incY;
}Direction;//分别表示横纵坐标的增加量
typedef struct {
    int x;
    int y;
    int di;
}Box;//分别表示横纵坐标和移动方向
typedef struct Node{
    Box data;
    struct Node* next;
}Node;
int main() {
    Direction direct[4];
    direct[0].incX=0,direct[0].incY=1;//右
    direct[1].incX=1,direct[1].incY=0;//下
    direct[2].incX=0,direct[2].incY=-1;//左
    direct[3].incX=-1,direct[3].incY=0;//上
    return 0;
}

下面这张图就是我们direct数组初始化后的效果图:
在这里插入图片描述

2.实现栈的基本功能(基本功)

Pstack initsta() { // 初始化栈
    Pstack s = (Pstack)malloc(sizeof(Stack));
    Pnode phead = (Pnode)malloc(sizeof(Node));
    s->pButtom = phead;
    s->pTop = phead;
    return s;
}

int push(Pstack s, box key) { // 压栈
    Pnode pNew = (Pnode)malloc(sizeof(Node));
    pNew->pNext = s->pTop;
    s->pTop = pNew;
    pNew->data.x = key.x;
    pNew->data.y = key.y;
    pNew->data.fx = key.fx;
    return 0;
}

box pop(Pstack s) { // 出栈
    box tmp;
    if (s->pTop != s->pButtom) {
        Pnode pTmp = s->pTop->pNext;
        tmp.x = s->pTop->data.x;
        tmp.y = s->pTop->data.y;
        tmp.fx = s->pTop->data.fx;
        free(s->pTop);
        s->pTop = pTmp;
    }
    return tmp;
}

bool empty(Pstack s) { // 判断栈空
    if (s->pTop == s->pButtom)
        return true;
    else
        return false;
}

3.逆序输出栈中元素(难点之一)

这里给大家贴一个地址,一开始我也是一头雾水,看了别人的讲解才慢慢有了思路
https://blog.csdn.net/u012011079/article/details/113706223

这里面用到了栈与递归的思想,希望大家辅助别人的思想仔细体会,动手敲一下

// 递归逆序输出栈中元素
void recursiveReverse(Pstack s) {
    if (empty(s)) {
        return;
    }
    box tmp = pop(s);
    recursiveReverse(s);
    printf("(%d,%d)\n", tmp.x, tmp.y);
}

4. 拼凑函数与具体实现

前面基本上就是对于懒猫老师课上给的伪代码进行准备工作,具体是主函数findpath传入的每一个参数怎么实现,而下面则是对于课上代码的具体演示,可能会有很多改进的地方,对于上面的一些代码,我也是有很多不太明白或者遗忘的地方,也是看着别人的贴子一点一点对着理解然后又复制粘贴对于一些报错修改后,才形成了可以运行的代码,这里采用的是链栈,但希望大家对于下面的函数的每一步一定要弄明白,特别是对于这些if-else结构到底是怎么回事,一定要理解透彻,可以借助我的笔记,很详细!
在这里插入图片描述

bool findpath(int maze[][6], direction Dir[], Pstack s) {
    box tmp; // 栈中操作的元素
    int x, y, fx;
    int row, col;

    maze[1][1] = -1;
    tmp.x = 1;
    tmp.y = 1;
    tmp.fx = -1;
    push(s, tmp); // 迷宫入口进栈

    while (!empty(s)) { // 栈不空, 循环
        tmp = pop(s); // 出栈
        x = tmp.x;
        y = tmp.y;
        fx = tmp.fx + 1;

        while (fx < 4) {
            row = x + Dir[fx].incx;
            col = y + Dir[fx].incy;

            if (maze[row][col] == 0) {
                box newTmp;
                newTmp.x = x;
                newTmp.y = y;
                newTmp.fx = fx;
                push(s, newTmp);
                x = row;
                y = col;
                maze[row][col] = -1;

                if (row == M && col == N) {
                    box endTmp;
                    endTmp.x = row;
                    endTmp.y = col;
                    endTmp.fx = -1;
                    push(s, endTmp);
                    return true;
                } else {
                    fx = 0;
                }
            } else {
                fx++;
            }
        }
    }

5.笔记

在这里插入图片描述
在这里插入图片描述

6.main函数

int main() {
    int maze[M+2][N+2] = {
        {1,1,1,1,1,1},
        {1,0,0,0,0,1},
        {1,1,0,1,1,1},
        {1,0,0,0,1,1},
        {1,1,1,0,0,1},
        {1,1,1,1,1,1}
    }; // 迷宫二维数组
    direction Dir[4] = {
        {0,1},
        {1,0},
        {0,-1},
        {-1,0}
    }; // 探测方向二维数组
    Pstack s = initsta();
    if (findpath(maze, Dir, s)) {
        printf("find path\n");
        recursiveReverse(s); // 使用递归函数逆序输出路径
    } else {
        printf("no path\n");
    }
    return 0;
}

结语

总的来说,这个算法比较难,不仅需要扎实的基础,还需要有一定的算法思维,对于各种问题的解决在懒猫老师的课程上都有,希望大家继续加油,整理不易,请多多点赞收藏关注,蟹蟹!等后续我彻底理解之后会在最后附上C++版本,而且事实上我认为这样会更简洁明了,易于理解

标签:tmp,return,fx,迷宫,direct,DFS,int,详解,pTop
From: https://blog.csdn.net/2402_88307286/article/details/145098790

相关文章

  • JMeter 命令行利器:-J 参数详解
    JMeter命令行利器:-J参数详解在进行JMeter性能测试时,命令行模式提供了更大的灵活性和自动化能力。其中,-J参数是JMeter命令行选项中一个非常重要的组成部分,它允许我们设置Java系统属性,从而影响JMeter的各种行为,包括配置、日志、插件以及其他各种设置。我们深入探讨-J......
  • 详解MySQL数据库和部署
    部署一个基本的数据库系统通常包括以下几个步骤:规划、安装、配置、安全设置、测试以及日常工作。下面以部署MySQL数据库维护为例进行详细讲解:1.规划在部署数据库前需要明确以下内容:用途:明确数据库的使用场景(例如Web应用、数据分析)。环境:选择操作系统(如CentOS7)、硬件资源(C......
  • MySQL 权限详解
    All/AllPrivileges权限代表全局或者全数据库对象级别的所有权限Alter权限代表允许修改表结构的权限,但必须要求有create和insert权限配合。如果是rename表名,则要求有alter和drop原表,create和insert新表的权限Alterroutine权限代表允许修改或者删除存储过程、函数的权限......
  • 深入HDFS——元数据管理
    引入通过前面的学习积累,我们对HDFS已经有了不错的理解,但是学习技术,还是要从细微处见真章!今天就通过深入NameNode源码,深入看看HDFS是如何实现元数据管理的。关于源码阅读,我常用的思路是:先对相关技术有一个大致的了解,针对里面感兴趣,或者疑惑的地方,换位思考一下自己来会怎么......
  • Java 语法糖详解
    什么是语法糖?语法糖(SyntacticSugar) 也称糖衣语法,是英国计算机学家Peter.J.Landin发明的一个术语,指在计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。简而言之,语法糖让程序更加简洁,有更高的可读性。 有意思的是,在编程领域,除了语法糖......
  • 智能合约中的多个函数重入攻击(Reentrancy Attack)详解
    简介在区块链智能合约开发中,重入攻击(ReentrancyAttack)是一种非常危险的漏洞类型。攻击者通过利用合约内函数之间的调用漏洞,可能会重复调用某个函数或多个函数,从而导致不正常的行为,甚至损失资金。通常,重入攻击依赖于合约执行过程中状态更新与外部合约交互的顺序错误。在这篇......
  • JavaScript详解 ——函数
    1、函数的概念在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码需要大量重复使用函数:就是封装一段可被重复调用执行的代码块。通过代码块可以实现在需要的的重复使用,使用typeof检查一个函数对象时,会返回function函数的封装是把一个或者多个功能通过函数的方式......
  • Python 文件和异常捕获(详解)
            前言:在Python编码中,我们会学到python中的文件的读取与写入,当然还有对文件夹的操作,在文章的最后还有异常捕获的详细解释~~一.文件的概念:        有名称:每个文件都有一个文件名,用于在特定的文件系统中唯一标识该文件,方便用户和系统对文件进行识别、访......
  • Qt/C++ 基于回调模式的海康3D相机开发流程详解(附工程源码、开发文档下载链接)
    本文将基于海康3D相机SDK的回调模式,通过具体代码讲解如何完成从设备初始化到图像采集的完整流程。以下是标准的流程图和具体的开发步骤。一、开发流程概述流程分为以下几个关键步骤:运行环境初始化:调用MV3D_LP_Initialize(),初始化SDK运行环境。设备发现:调用MV3D_LP_Get......
  • 深度剖析RabbitMQ:从基础组件到管理页面详解
    文章目录一、简介二、Overview2.1Overview->Totals2.2Overview->Nodesbroker的属性2.3Overview->Churnstatistics2.4Overview->Portsandcontexts2.5Overview->Exportdefinitions2.6Overview->Importdefinitions三、Connections连接的属性四、Channels通道的......