从迷宫问题理解dfs

文章目录

  • 迷宫问题打印路径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;
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

掌握Node Version Manager(nvm):跨平台Node.js版本管理

&#x1f31f; 前言 欢迎来到我的技术小宇宙&#xff01;&#x1f30c; 这里不仅是我记录技术点滴的后花园&#xff0c;也是我分享学习心得和项目经验的乐园。&#x1f4da; 无论你是技术小白还是资深大牛&#xff0c;这里总有一些内容能触动你的好奇心。&#x1f50d; &#x…

整合阿里云短信服务

1. 申请服务 如图&#xff1a; 申请签名管理和模板管理 2. 进入快速学习和调试 2.1 进入快速学习 2.2 获取依赖和代码实现 3. 具体实现案例 3.1 添加依赖 <dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifact…

9.MMD 基础内容总结及制作成品流程

前期准备 1. 导入场景和模型 在左上角菜单栏&#xff0c;显示里将编辑模型时保持相机和光照勾选上&#xff0c;有助于后期调色 将抗锯齿和各向异性过滤勾掉&#xff0c;可以节省资源&#xff0c;避免bug 在分辨率设定窗口&#xff0c;可以调整分辨率 3840x2160 4k分辨率 1…

Umi.js:登录之后需要手动刷新权限菜单才能渲染

在使用Umi.js开发后台管理页面时&#xff0c;用户登录之后&#xff0c;总是需要手动刷新一次页面&#xff0c;才能够拿到全局状态/权限信息。 问题描述 结合使用umi/plugin-layout和umi/plugin-access&#xff0c;登录进入页面&#xff0c;配置的权限菜单未渲染&#xff0c;需…

【Redis 神秘大陆】005 常见性能优化方式

五、Redis 性能优化 5.1 系统层面的优化 https://github.com/sohutv/cachecloud/blob/main/redis-ecs/script/cachecloud-init.sh initConfig() {# 支持虚拟内存分配sysctl vm.overcommit_memory1# 最大排队连接数设置为 511&#xff0c;一般默认是 128echo 511 >/proc/sy…

openobserve-filebeat配置

优势 rustgolang开发的日志工具组合&#xff0c;自带日志数据存储&#xff0c;简化部署和管理。日志数据可配置保留x天。从日志文件中采集&#xff0c;做到非侵入式日志集中管理。 可从日志内容中提取信息进行报警等二次开发。 下载 openobserve-v0.10.1-windows-amd64 fil…

【题解】NC40链表相加(二)(链表 + 高精度加法)

https://www.nowcoder.com/practice/c56f6c70fb3f4849bc56e33ff2a50b6b?tpId196&tqId37147&ru/exam/oj class Solution {public:// 逆序链表ListNode* reverse(ListNode* head) {// 创建一个新节点作为逆序后链表的头节点ListNode* newHead new ListNode(0);// 当前…

使用51单片机控制T0和T1分别间隔1秒2秒亮灭逻辑

#include <reg51.h>sbit LED1 P1^0; // 设置LED1灯的接口 sbit LED2 P1^1; // 设置LED2灯的接口unsigned int cnt1 0; // 设置LED1灯的定时器溢出次数 unsigned int cnt2 0; // 设置LED2灯的定时器溢出次数// 定时器T0 void Init_Timer0() {TMOD | 0x01;; // 定时器…

代码学习记录49---单调栈

随想录日记part49 t i m e &#xff1a; time&#xff1a; time&#xff1a; 2024.04.20 主要内容&#xff1a;今天开始要学习单调栈的相关知识了&#xff0c;今天的内容主要涉及&#xff1a;柱状图中最大的矩形 84.柱状图中最大的矩形 Topic184.柱状图中最大的矩形 题目&…

Sharding-JDBC笔记1

Sharding-JDBC笔记1 1.分库分表1.1 垂直分库1.2 垂直分表1.3 水平分库1.4 水平分表 2.存在问题2.1 事务一致性2.2 跨节点关联查询2.3 跨节点分页、排序函数2.4 主键避重2.5 公共表 1.分库分表 分库分表就是为了解决由于数据量过大而导致数据库性能降低的问题&#xff0c;将原来…

操作符不存在:sde.st_geometry ^ !sde.st_geometry建议 SQL函 数st_intersects在内联inlining期间

操作符不存在&#xff1a;sde.st_geometry ^ &#xff01;sde.st_geometry建议 SQL函 数st_intersects在内联inlining期间 问题&#xff1a;最近在使用SQL图形处理函数处理图形时&#xff0c;莫名奇妙报如下错误&#xff0c;甚是费解 于是开始四处"寻医问药" 1、nav…

Spark集群的搭建

1.1搭建Spark集群 Spark集群环境可分为单机版环境、单机伪分布式环境和完全分布式环境。本节任务是学习如何搭建不同模式的Spark集群&#xff0c;并查看Spark的服务监控。读者可从官网下载Spark安装包&#xff0c;本文使用的是spark-2.0.0-bin-hadoop2.7.gz。 1.1.1搭建单机版…

“开挂”的WAAP全站防护是云海驰骋的必备

何为攻击&#xff1f; 网络和应用是攻击的两大阵地 网络攻击像僵尸&#xff1a;简单、粗暴、让人猝不及防 显著特征&#xff1a;流量大&#xff0c;并发高 应用攻击像幽灵&#xff1a;复杂、神秘、让人摸不着头脑 显著特征&#xff1a;流量小、隐蔽强 攻击不像“馅饼”&…

OpenHarmony实战开发-组件复用实践。

若开发者的应用中存在以下场景&#xff0c;并成为UI线程的帧率瓶颈&#xff0c;应该考虑使用组件复用机制提升应用性能&#xff1a; 滑动场景下对同一类自定义组件的实例进行频繁的创建与销毁。反复切换条件渲染的控制分支&#xff0c;且控制分支中的组件子树结构比较复杂。 …

SpringBoot3 + Vue3 + Element-Plus + TS 实现动态二级菜单级联选择器

SpringBoot3 Vue3 Element-Plus TS 实现动态二级菜单选择器 1、效果展示1.1 点击效果1.2 选择效果1.3 返回值1.4 模拟后端返回数据 2、前端代码2.1 UnusedList.vue2.2 goodsType.ts2.3 http.ts 3、后端代码3.1 GoodsCategoryController.java3.2 GoodsCategoryService.java3.…

读后感-有效沟通

司内的学习已开展8期&#xff0c;内容主要以如何沟通为主&#xff0c;这里将根据个人的学习体会&#xff0c;对所学内容进行梳理与整合&#xff0c;以期更好地吸收和应用所学知识。 沟通是一门技术&#xff0c;其轨迹可循。自来熟的态度&#xff0c;一上来便滔滔不绝地发表言论…

ThingsBoard系统层配置邮件发送

1、前沿 2、案例 1、管理员的身份进行登录 2、选择账户&#xff0c;并将邮箱更改为自己的邮箱&#xff0c;并保存配置 3、退出账号&#xff0c;使用邮箱进行登录&#xff0c;密码还是跟之前一样 4、登录后选择设置-发送邮件 5、登录邮箱申请邮箱的密钥 ​7、 按照图片填…

Mysql The last packet sent successfully to the server was 0 milliseconds ago.

项目启动后&#xff0c;报错&#xff0c;但是我的navicat 数据库连接工具是连接上的&#xff0c;没有问题的&#xff0c;但是程序就是连接不上。端口放开了&#xff0c;防火墙也放开了 先说问题&#xff1a;是网络问题&#xff0c; 如何解决&#xff1a;因为我的机子上又跑了…

计算机网络——数据链路层(介质访问控制)

计算机网络——数据链路层&#xff08;介质访问控制&#xff09; 介质访问控制静态划分信道动态划分信道ALOHA协议纯ALOHA&#xff08;Pure ALOHA&#xff09;原理特点 分槽ALOHA&#xff08;Slotted ALOHA&#xff09;原理特点 CSMA协议工作流程特点 CSMA-CD 协议工作原理主要…

RabbitMQ学习记录

核心概念 Brocker&#xff1a;消息队列服务器实体 Exchange(消息交换机)&#xff1a;它指定消息按什么规则&#xff0c;路由到哪个队列。 Queue(消息队列载体)&#xff1a;每个消息都会被投入到一个或多个队列。 Binding(绑定)&#xff1a;它的作用就是把exchange和queue按…