从迷宫问题理解dfs

news2024/12/28 4:15:44

文章目录

  • 迷宫问题打印路径1
    • 思路
      • 定义一个结构体
      • 要保存所走的路径,就需要使用到栈
      • 遍历所有的可能性
      • 核心代码
    • 部分函数递归图
    • 源代码
  • 迷宫问题返回最短路径
    • 这里的思想同上面类似。
    • 源代码

迷宫问题打印路径1

定义一个二维数组 N*M ,如 5 × 5 数组下所示:

int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。

输入描述:
输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

输出描述:
左上角到右下角的最短路径
输入:
5 5
0 1 0 0 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出:
(0,0)
(1,0)
(2,0)
(2,1)
(2,2)
(2,3)
(2,4)
(3,4)
(4,4)

思路

定义一个结构体

typedef struct pt {
	//行·
    int row;
    //列
    int col;
}PT;

要保存所走的路径,就需要使用到栈

  导入c++的 STL栈。
如果是c语言就需要自己手写栈。
c语言的栈

遍历所有的可能性

在这里插入图片描述

核心代码

  遍历上,右,左,下四个方向。先上核心代码。

bool isPath(int** a, int n, int m, PT pt)
{
    if (pt.row >= 0 && pt.row < n
        && pt.col >= 0 && pt.col < m
        && a[pt.row][pt.col] == 0)
    {
        return true;
    }
    else {
        return false;
    }
}

//这里只需要一条路,直接返回bool值
bool dfs(int** a, int n, int m, PT pt)
{
    st.push(pt);
    if (pt.row == n - 1 && pt.col == m - 1)
    {
        //找到出口
        return true;
    }
	//标记走过的路为2
    a[pt.row][pt.col] = 2;

    //开始遍历四个方向
    //上
    PT next = pt;
    next.row -= 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }


    //右
    next.row += 1;
    next.col += 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }

    //下
    next.col -= 1;
    next.row += 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }

    //左
    next.row -= 1;
    next.col -= 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }

    st.pop();

    //四个方向都不行,则false;
    return false;
}

部分函数递归图

开始按照每个点的上,右,左,下开始前进,如果可以走,则进行标记为2,如果一个方向不可以走,则换另一个方向,直到四个方向都不可以走,则返回上一个正确的位置。
在这里插入图片描述

源代码

// https://www.nowcoder.com/practice/cf24906056f4488c9ddb132f317e03bc?tpId=37&tqId=21266&ru=/exam/oj

#include <iostream>
using namespace std;
#include<stack>

typedef struct pt {
    int row;
    int col;
}PT;

stack<PT> st;

bool isPath(int** a, int n, int m, PT pt)
{
    if (pt.row >= 0 && pt.row < n
        && pt.col >= 0 && pt.col < m
        && a[pt.row][pt.col] == 0)
    {
        return true;
    }
    else {
        return false;
    }
}

//这里只需要一条路,直接返回bool值
bool dfs(int** a, int n, int m, PT pt)
{
    st.push(pt);
    if (pt.row == n - 1 && pt.col == m - 1)
    {
        //找到出口
        return true;
    }

    a[pt.row][pt.col] = 2;

    //开始遍历四个方向
    //上
    PT next = pt;
    next.row -= 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }


    //右
    next.row += 1;
    next.col += 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }

    //下
    next.col -= 1;
    next.row += 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }

    //左
    next.row -= 1;
    next.col -= 1;
    if (isPath(a, n, m, next))
    {
        if (dfs(a, n, m, next))
        {
            return true;
        }
    }

    st.pop();

    //四个方向都不行,则false;
    return false;
}

void Print(stack<PT> st)
{
    stack<PT> rt;
    while (!st.empty())
    {
        rt.push(st.top());
        st.pop();
    }
    while (!rt.empty())
    {
        cout << "(" << rt.top().row << "," << rt.top().col << ")" << endl;
        rt.pop();
    }
}

int main() {
    int n, m;
    while (cin >> n >> m) { // 注意 while 处理多个 case
        //开辟一个动态二维数组
        int** tmp = (int**)malloc(sizeof(int*) * n);
        for (int i = 0; i < n; ++i)
        {
            tmp[i] = (int*)malloc(sizeof(int) * m);
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < m; ++j)
            {
                cin >> tmp[i][j];
            }
        }
        //定义结构体
        PT pt;

        pt.row = 0;
        pt.col = 0;
        bool flag = dfs(tmp, n, m, pt);
        if (flag == true)
        {
            Print(st);
        }
    }

}

迷宫问题返回最短路径

描述
小青蛙有一天不小心落入了一个地下迷宫,小青蛙希望用自己仅剩的体力值P跳出这个地下迷宫。为了让问题简单,假设这是一个n*m的格子迷宫,迷宫每个位置为0或者1,0代表这个位置有障碍物,小青蛙达到不了这个位置;1代表小青蛙可以达到的位置。小青蛙初始在(0,0)位置,地下迷宫的出口在(0,m-1)(保证这两个位置都是1,并且保证一定有起点到终点可达的路径),小青蛙在迷宫中水平移动一个单位距离需要消耗1点体力值,向上爬一个单位距离需要消耗3个单位的体力值,向下移动不消耗体力值,当小青蛙的体力值等于0的时候还没有到达出口,小青蛙将无法逃离迷宫。现在需要你帮助小青蛙计算出能否用仅剩的体力值跳出迷宫(即达到(0,m-1)位置)。
输入描述:
输入包括n+1行:
第一行为三个整数n,m(3 <= m,n <= 10),P(1 <= P <= 100)
接下来的n行:
每行m个0或者1,以空格分隔
输出描述:
如果能逃离迷宫,则输出一行体力消耗最小的路径,输出格式见样例所示;如果不能逃离迷宫,则输出"Can not escape!"。 测试数据保证答案唯一
输入4 4 10 1 0 0 1 1 1 0 1 0 1 1 1 0 0 1 1
[0,0],[1,0],[1,1],[2,1],[2,2],[2,3],[1,3],[0,3]

这里的思想同上面类似。

  但是也有略微区别,这里要求最短路径,我们怎么知道求出的答案就是最短的路劲呢?所以这里要遍历所有可以前进的路线。走的路径进行标记,不走的路劲标记过的要取消标记。

源代码

#include <iostream>
using namespace std;
#include<stack>

//定义坐标

typedef struct pt {
    int row;
    int col;
}PT;

//普通路径
stack<PT> st;
//最短路径
stack<PT> minSt;

//判断能否通过
bool isPath(int** tmp, int n, int m, PT pt)
{
    if (pt.row >= 0 && pt.row < n
        && pt.col >= 0 && pt.col < m
        && tmp[pt.row][pt.col] == 1
        )
    {
        return true;
    }
    else {
        return false;
    }
}


//这里我们要找到·所有路径,所以不用返回
void dfs(int** tmp, int n, int m, PT pt, int p)
{

    //每次进来先入栈
    st.push(pt);
    //走过的路标记为2
    tmp[pt.row][pt.col] = 2;

    if (p >= 0 && pt.row == 0 && pt.col == m - 1)
    {
        //更新最短路径
        if (st.size() < minSt.size() ||
            minSt.empty())
        {
            minSt = st;
        }
    }

    //枚举所有方法
    PT next;

    //上
    next = pt;
    next.row -= 1;
    if (isPath(tmp, n, m, next))
    {
        dfs(tmp, n, m, next, p - 3);
    }

    //右
    next = pt;
    next.col += 1;
    if (isPath(tmp, n, m, next))
    {
        dfs(tmp, n, m, next, p - 1);
    }

    //下
    next = pt;
    next.row += 1;
    if (isPath(tmp, n, m, next))
    {
        dfs(tmp, n, m, next, p);
    }

    //左
    next = pt;
    next.col -= 1;
    if (isPath(tmp, n, m, next))
    {
        dfs(tmp, n, m, next, p - 1);
    }

    //都不能走,还原路径为1
    tmp[pt.row][pt.col] = 1;
    st.pop();
    //四个方向都不能走
}

//进行对栈的打印
void Print(stack<PT> st)
{
    stack<PT> rt;
    while (!st.empty())
    {
        rt.push(st.top());
        st.pop();
    }
    while (rt.size() > 1)
    {
        cout << "[" << rt.top().row << "," << rt.top().col << "]" << ",";
        rt.pop();
    }
    cout << "[" << rt.top().row << "," << rt.top().col << "]" << endl;
    rt.pop();
}

int main() {
    int n, m, p;
    while (cin >> n >> m) { // 注意 while 处理多个 case
        cin >> p;
        //开辟二维数组
        int** tmp = (int**)malloc(sizeof(int*) * n);
        for (int i = 0; i < n; ++i)
        {
            tmp[i] = (int*)malloc(sizeof(int) * m);
        }
        //输入
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < m; ++j)
            {
                cin >> tmp[i][j];
            }
        }
        PT pt;
        pt.row = 0;
        pt.col = 0;
        dfs(tmp, n, m, pt, p);




        if (!minSt.empty())
        {
            Print(minSt);
        }
        else {
            cout << "Can not escape!" << endl;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1614111.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我与C++的爱恋:隐式类型转换

​ ​ &#x1f525;个人主页&#xff1a;guoguoqiang. &#x1f525;专栏&#xff1a;我与C的爱恋 朋友们大家好&#xff0c;本篇内容我们来介绍初始化列表&#xff0c;隐式类型转换以及explicit的内容 一、初始化列表 1.1 构造函数体赋值 在创建对象时&#xff0c;编译器…

WP-AutoPostPro 汉化版: WordPress自动采集发布插件

WP-AutoPostPro 是目前最好用的WordPress自动采集发布插件&#xff0c;最大的特点是可以采集来自于任何网站的内容并自动发布到你的WordPress站点。真正做到可以采集任何网站的内容并自动发布&#xff0c;采集过程完全自动进行无需人工干预&#xff0c;并提供内容过滤、HTML标签…

C++从入门到精通——模板

模板 前言一、泛型编程二、函数模板函数模板的概念函数模板格式示例 函数模板的原理函数模板的实例化隐式实例化显式实例化示例 auto做模板函数的返回值模板参数的匹配原则总结 三、类模板类模板的定义格式类模板的实例化 前言 C模板是C语言中的一种泛型编程技术&#xff0c;可…

用ESP32的ADC引脚,结合分压电路测量电压

该代码基于ESP32&#xff08;Arduino库&#xff09;实现ADC&#xff08;模拟数字转换器&#xff09;数据采集。它配置ADC参数、获取校准特性&#xff0c;循环采样并计算平均值&#xff0c;将ADC读数转换为电压&#xff0c;考虑分压电阻影响&#xff0c;计算实际电压值&#xff…

SpringBoot 根据不同环境切换不同文件路径

最简单的办法就是使用多个 application.yml 配置文件 。一个叫 application-test.yml 测试用&#xff1b;另一个是正式使用的 application-prod.yml 。win环境下大部分是开发测试时候使用的&#xff0c;服务正式上线需要部署在Linux服务器上又换成了Linux。但开发初期或者项目…

SEGGER Embedded Studio IDE移植FreeRTOS

SEGGER Embedded Studio IDE移植FreeRTOS 一、简介二、技术路线2.1 获取FreeRTOS源码2.2 将必要的文件复制到工程中2.2.1 移植C文件2.2.2 移植portable文件2.2.3 移植头文件 2.3 创建FreeRTOSConfig.h并进行配置2.3.1 处理中断优先级2.3.2 configASSERT( x )的处理2.3.3 关于系…

Unity3D 爆火的休闲益智游戏工程源码/3D资源 大合集

Unity3D休闲益智游戏工程源码大合集 一、关卡类游戏工程源码二、跑酷类游戏工程源码三、消除合成类游戏工程源码四、棋牌类游戏工程源码五、RPG(角色扮演)类游戏工程源码六、FPS&#xff08;射击&#xff09;类游戏工程源码十、Unity3D工艺仿真六、Unity游戏资源1、Unity3D 吃鸡…

金融时报:波场亮相哈佛大学并举办TRON Builder Tour活动

近日,波场TRON作为顶级白金赞助商出席哈佛区块链会议并成功举办TRON Builder Tour哈佛站活动,引发海外媒体热议。美联社、金融时报、Cointelegraph等国际主流媒体及加密知名媒体均对此给予了高度评价,认为本次大会对TRON Builder Tour活动具有里程碑意义,彰显了波场TRON致力于促…

护眼台灯什么品牌好?台灯的十大品牌推荐

长时间的使用眼睛&#xff0c;出现疲劳感就会对眼睛造成伤害&#xff0c;最常见的场景就是青少年儿童学习看书&#xff0c;成年人晚上工作时。相信不少人就是这样度过的&#xff0c;因此数据表明目前中国近视患者超过6亿人。所以想要拥有一个良好的视力健康一款光源合适的台灯是…

【数据结构】栈和队列(链表模拟队列)

学习本章节必须具备 单链表的前置知识&#xff0c; 建议提前学习&#xff1a;点击链接学习&#xff1a;单链表各种功能函数 细节 详解 本章节是学习用 单链表模拟队列 1. 单链表实现队列 思路如下 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数…

代码中哪些复杂的结构图是怎么画出来的?

最近找到一个在线的代码架构图生成器&#xff0c;你只要画出结构图&#xff0c;就会自动生成代码示意图&#xff1a; https://asciiflow.com/#/

计算机网络—TCP协议详解:协议构成、深度解析(3)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;マリンブルーの庭園—ずっと真夜中でいいのに。 0:34━━━━━━️&#x1f49f;──────── 3:34 &#x1f504; ◀️…

变频电源都有哪些故障?

变频电源是一种可以将市电的交流电转换为频率可调的交流电的电力电子设备&#xff0c;它可以根据需求调整输出电压和频率&#xff0c;为设备运行提供稳定可靠的电源。但是在实际使用过程中常会遇到一些故障&#xff0c;今天纳米软件将介绍这些故障以及解决办法。 1. 短路 短路故…

开源项目实现简单实用的股票回测

1 引言 之前&#xff0c;尝试做股票工具一直想做的大而全&#xff0c;试图抓取长期的各个维度数据&#xff0c;然后统计或者训练模型。想把每个细节做到完美&#xff0c;结果却陷入了细节之中&#xff0c;最后烂尾了。 最近&#xff0c;听到大家分享了一些关于深度学习、时序…

【xhs爬虫软件】把小红书评论comment接口封装成GUI采集工具!

用Python开发爬虫采集软件&#xff0c;可自动抓取小红书评论数据&#xff0c;并且含二级评论。 小红书的评论接口URL是&#xff1a; https://edith.xiaohongshu.com/api/sns/web/v2/comment/page 开发者模式分析过程&#xff1a; 进而封装成GUI界面软件&#xff0c;如下&…

【Axure教程0基础入门】05动态面板

05动态面板 1.动态面板是什么&#xff1f; 一个用来存放多个元件的容器&#xff08;container&#xff09; 其中包含多个状态&#xff08;state&#xff09;&#xff0c;但同时只能显示一个 状态之间&#xff0c;可以通过交互动作&#xff08;action&#xff09;控制切换和动…

【Spring Cloud】服务容错中间件Sentinel进阶——五大规则

文章目录 Sentinel的概念和功能基本概念资源规则 重要功能流量控制熔断降级系统负载保护 SentineI 规则流控规则简单配置配置流控模式直接流控模式关联流控模式链路流控模式 配置流控效果 熔断规则慢调用比例异常比例异常数 热点规则热点规则简单使用热点规则增强使用 授权规则…

请编写函数fun,该函数的功能是:移动字符串中的内容,移动的规则如下:把第1到第m个字符,平移到字符串的最后,把第m+l到最后的字符移到字符串的前部。

本文收录于专栏:算法之翼 https://blog.csdn.net/weixin_52908342/category_10943144.html 订阅后本专栏全部文章可见。 本文含有题目的题干、解题思路、解题思路、解题代码、代码解析。本文分别包含C语言、C++、Java、Python四种语言的解法完整代码和详细的解析。 题干 请编…

Ai-WB2 系列模组SDK接入亚马逊

文章目录 前言一、准备二、亚马逊云物模型建立1. 注册亚马逊账号&#xff0c;登录AWS IoT控制台&#xff0c;[注册地址](https://aws.amazon.com/cn/)2. 创建好之后点击登录3. 创建物品以及下载证书 三、连接亚马逊云demo获取以及配置1. 下载源码2. 按照顺序执行下面指令3. 修改…

2024接口自动化测试高频面试题【建议收藏】

一、json和字典的区别&#xff1f; json就是一个文本、字符串&#xff1b;有固定的格式&#xff0c;格式长的像python字典和列表的组合&#xff1b;以key-value的键值对形式来保存数据&#xff0c;结构清晰&#xff0c;。可以说是目前互联网项目开发中最常用的一种数据交互格式…