每日一题——迷宫问题(I)

迷宫问题——I

题目链接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Byc8IMyw-1689939530325)(C:/Users/HUASHUO/AppData/Roaming/Typora/typora-user-images/image-20230721185440823.png)]

思路

创建二维数组,并实现输入

首先输入二维数组的行和列:

int n, m;
scanf("%d%d", &n, &m);

然后动态开辟二维数组:

注:对动态开辟还不太了解的同学可以看看👉C语言——动态内存管理

int** nums = (int**)malloc(sizeof(int*) * n);
for (int i = 0; i < n; i++)
{nums[i] = (int*)malloc(sizeof(int) * m);
}

最后向二维数组输入数据,形成迷宫

for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)scanf("%d", &nums[i][j]);

实现找路(FindWay)

首先,为了方便记录,我们可以定义一个结构体来记录二维数组每一个位置的坐标

注:对结构体操作不太了解的小伙伴看这里👉传送门

typedef struct Position
{int row;int col;
}POS;

接着,我们应该确定找路的整体思路

  1. 从上、下、左、右四个方向分别探路
  2. 探路之前,要对将要前进到区域进行有效性判断,如果符合条件再前进,否则选择下一个方向
  3. 如果,四个方向都无法前进,那么说明是个死路,就要进行回溯,由此,可以推出,需要用递归算法实现
  4. 由回溯的位置再次选择方向前进,为了避免走相同的路,我们应该在走过的每个点位做上标记,例如修改为除0,1的数据

判断位置有效性(Judge):

bool Judge(int** nums, int n, int m, POS pos)
{/*如果数组越界或者该点位的数据不是0就说明该点位无效,不能前进*/if (pos.col >= m || pos.col < 0 ||pos.row >= n || pos.row < 0 ||nums[pos.row][pos.col] != 0){return false;}elsereturn true;
}

FindWay主体:

FindWay(int** nums, int n, int m, POS entry)
{nums[entry.row][entry.col] = -1;//上POS next = entry;next.row--;if (Judge(nums, n, m, next)){FindWay(nums, n, m, next)}//下next = entry;next.row++;if (Judge(nums, n, m, next)){FindWay(nums, n, m, next)}//左next = entry;next.col--;if (Judge(nums, n, m, next)){FindWay(nums, n, m, next)}//右next = entry;next.col++;if (Judge(nums, n, m, next)){FindWay(nums, n, m, next)}
}

这样写会造成一个问题:经过调试我们可以发现,这个函数并没有实现走到右下角(出口)便结束的功能,这个函数结束时,停留的位置会在出口处(因为可以走的的地方全部被标记为-1,当无路可走的时候就会回溯,最后就会回到出口),因此,我们可以将FindWay()函数的返回值设定为bood类型,当走到出口时就退出函数:

bool FindWay(int** nums, int n, int m, POS entry)
{if(entry.row == n - 1 && entry.col == m - 1)return true;nums[entry.row][entry.col] = -1;//上POS next = entry;next.row--;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true;}//下next = entry;next.row++;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true;}//左next = entry;next.col--;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true; }//右next = entry;next.col++;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true;}return false;
}

保存正确的路径

很容易想到,我们可以用一个数组来保存我们每走过的下标位置。但是当我们进行回溯的时候又要不断对无效的路径进行删除,可见只是单纯的用一个数组是不方便实现的。

我们可以用栈的“先入后出”的特性来实现

注:对于栈的基本操作还不太熟悉的小伙伴可以看看👉栈的基本操作

  • 每走到一个位置,就将这个位置入栈
  • 如果走到的位置无法前进,就说明这个点位是思路,需要回溯,每回溯一个点位,就需要将这个点位删除(出栈)
bool FindWay(int** nums, int n, int m, POS entry)
{StackPush(&STACK, entry);if(entry.row == n - 1 && entry.col == m - 1)return true;nums[entry.row][entry.col] = -1;//上POS next = entry;next.row--;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true;}//下next = entry;next.row++;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true;}//左next = entry;next.col--;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true; }//右next = entry;next.col++;if (Judge(nums, n, m, next)){if (FindWay(nums, n, m, next))return true;}StackPop(&STACK);return false;
}

打印路径

由于栈的“先入后出”的特性,取出栈的数据只能从栈顶到栈底取,因此如果我们直接对栈的数据进行打印,那么这个路径就是倒序(出口->入口)的。

为了得到正序(入口->出口)的路径,我们可以建立一个辅助栈,先将原有栈的数据逐个出栈到辅助栈中,再打印辅助栈的数据,这样就可以做到正序打印路径了。

void PrintWay()
{ST* stack = (ST*)malloc(sizeof(ST));StackInit(stack);while (!StackEmpty(&STACK)){POS temp = StackTop(&STACK);StackPop(&STACK);StackPush(stack, temp);}while (!StackEmpty(stack)){POS temp = StackTop(stack);StackPop(stack);printf("(%d,%d)\n", temp.row, temp.col);}
}

实现代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>typedef struct Position
{int row;int col;
}POS;typedef POS StackDataType;
typedef struct Stack
{StackDataType* data;int top;
}ST;ST STACK;	//定义一个全局栈//初始化栈
void StackInit(ST* stack)
{stack->top = 0;stack->data = (POS*)malloc(sizeof(POS) * 100);
}//判断栈空
bool StackEmpty(ST* stack)
{return stack->top == 0;
}//入栈
void StackPush(ST* stack, POS val)
{stack->data[(stack->top)++] = val;
}//出栈
void StackPop(ST* stack)
{assert(!StackEmpty(stack));stack->top--;
}//返回栈顶元素
StackDataType StackTop(ST* stack)
{return stack->data[stack->top - 1];
}//判断是否可以前进
bool Judge(int** nums, int n, int m, POS pos)
{if (pos.col >= m || pos.col < 0 ||pos.row >= n || pos.row < 0 ||nums[pos.row][pos.col] != 0){return false;}elsereturn true;
}//找路
bool FindWay(int** nums, int n, int m, POS entry)
{//先将该位置入栈StackPush(&STACK, entry);//判断是否已经到了出口if(entry.row == n - 1 && entry.col == m - 1)return true;//为了防止走相同的路,要对走过的路做标记nums[entry.row][entry.col] = -1;//上POS next = entry;next.row--;if (Judge(nums, n, m, next)){//如果到了出口,直接返回if (FindWay(nums, n, m, next))return true;}//下next = entry;next.row++;if (Judge(nums, n, m, next)){//如果到了出口,直接返回if (FindWay(nums, n, m, next))return true;}//左next = entry;next.col--;if (Judge(nums, n, m, next)){//如果到了出口,直接返回        if (FindWay(nums, n, m, next))return true; }//右next = entry;next.col++;if (Judge(nums, n, m, next)){//如果到了出口,直接返回        if (FindWay(nums, n, m, next))return true;}//如果是死路,就出栈,并返回假,说明没到出口StackPop(&STACK);return false;
}void PrintWay()
{//创建一个辅助栈ST* stack = (ST*)malloc(sizeof(ST));StackInit(stack);//将原始栈的数据放入辅助栈while (!StackEmpty(&STACK)){POS temp = StackTop(&STACK);StackPop(&STACK);StackPush(stack, temp);}//打印辅助栈的路径while (!StackEmpty(stack)){POS temp = StackTop(stack);StackPop(stack);printf("(%d,%d)\n", temp.row, temp.col);}
}int main()
{int n, m;scanf("%d%d", &n, &m);//动态申请二维数组int** nums = (int**)malloc(sizeof(int*) * n);for (int i = 0; i < n; i++){nums[i] = (int*)malloc(sizeof(int) * m);}//输入for (int i = 0; i < n; i++)for (int j = 0; j < m; j++)scanf("%d", &nums[i][j]);//初始化全局栈StackInit(&STACK);//找路POS entry = { 0,0 };FindWay(nums, n, m, entry);//打印路径PrintWay();return 0;
}

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

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

相关文章

CPU密集型和IO密集型任务的权衡:如何找到最佳平衡点

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、CPU密集型与IO密集型3.1、CPU密集型3.2、I/O密…

opencv-15 数字水印原理

最低有效位&#xff08;Least Significant Bit&#xff0c;LSB&#xff09;指的是一个二进制数中的第 0 位&#xff08;即最低位&#xff09;。 最低有效位信息隐藏指的是&#xff0c;将一个需要隐藏的二值图像信息嵌入载体图像的最低有效位&#xff0c;即将载体图像的最低有效…

再开源一款轻量内存池

前两天已开源线程池&#xff0c;开源一款轻量线程池项目&#xff0c;本节继续开源另一个孪生兄弟&#xff1a;内存池。 本节的线程池与内存池代码解析会在我的星球详细讲解。 内存池&#xff1a;https://github.com/Light-City/light-memory-pool 线程池&#xff1a;https://gi…

Python案例分析|使用Python图像处理库Pillow处理图像文件

本案例通过使用Python图像处理库Pillow&#xff0c;帮助大家进一步了解Python的基本概念&#xff1a;模块、对象、方法和函数的使用 使用Python语言解决实际问题时&#xff0c;往往需要使用由第三方开发的开源Python软件库。 本案例使用图像处理库Pillow中的模块、对象来处理…

ZooKeeper原理剖析

1.ZooKeeper简介 ZooKeeper是一个分布式、高可用性的协调服务。在大数据产品中主要提供两个功能&#xff1a; 帮助系统避免单点故障&#xff0c;建立可靠的应用程序。提供分布式协作服务和维护配置信息。 2.ZooKeeper结构 ZooKeeper集群中的节点分为三种角色&#xff1a;Le…

git如何撤销commit(未push)

文章目录 前言undo commitreset current branch to here Undo Commit&#xff0c;Revert Commit&#xff0c;Drop Commit的区别 是否删除对代码的修改是否删除Commit记录是否会新增Commit记录Undo Commit不会未Push会&#xff0c;已Push不会不会Revert Commit会不会会Drop Com…

vue 3.0 如何加载图片

.logo { background: url(~/assets/images/logo.svg) no-repeat center center/contain; width: 117px; height: 24px; margin: 0 20px; } <a class"logo" href"#"></a> 比较实用的书写方式

汽车销售数据可视化分析实战

1、任务 市场需求&#xff1a;各年度汽车总销量及环比&#xff0c;各车类、级别车辆销量及环比 消费能力/价位认知&#xff1a;车辆销售规模及环比、不同价位车销量及环比 企业/品牌竞争&#xff1a;各车系、厂商、品牌车销量及环比&#xff0c;市占率及变化趋势 热销车型&…

python多线程排查

问题 公司服务总是莫名其妙的cpu饱满排查了代码中的定时任务&#xff0c;排除之后仍经常出现类似问题。是时候debug了 排查过程 cpu劣化是一个过程&#xff0c;cpu持续增长到60%&#xff0c;然后突然服务雪崩不服务了。排查下来看sleep的物理线程和cpu增长的幅度一致 那么…

hadoop安全保护机制(kerberos + ldap)

信息安全理论&#xff1a; CIA模型&#xff1a;机密性、完整性和可用性 CIA模型能够帮助建议一些信息安全原则&#xff0c;但该模型并不是一个需要严格遵守的规则 hadoop平台可能设计多个CIA模型组件&#xff0c;也kennel一个也不涉及 机密性&#xff1a; 信息只应该被期望的…

探索AI图像安全,助力可信AI发展

探索AI图像安全&#xff0c;助力可信AI发展 0. 前言1. 人工智能发展与安全挑战1.1 人工智能及其发展1.2 人工智能安全挑战 2. WAIC 2023 多模态基础大模型的可信 AI2.1 WAIC 2023 专题论坛2.2 走进合合信息 3. AI 图像安全3.1 图像篡改检测3.2 生成式图像鉴别3.3 OCR 对抗攻击技…

Vis相关的期刊会议

中国计算机学会推荐国际学术会议和期刊目录 文档&#xff0c; 下载 link&#xff1a;CCF推荐国际学术刊物目录-中国计算机学会 一.可视化方向文章 1.IEEE VIS&#xff0c;是由 IEEE Visualization and Graphics Technical Committee(VGTC) 主办的数据可视化领域的顶级会议&a…

【计算机视觉 | 目标检测 | 图像分割】arxiv 计算机视觉关于目标检测和图像分割的学术速递(7 月 17 日论文合集)

文章目录 一、检测相关(5篇)1.1 TALL: Thumbnail Layout for Deepfake Video Detection1.2 Cloud Detection in Multispectral Satellite Images Using Support Vector Machines With Quantum Kernels1.3 Multimodal Motion Conditioned Diffusion Model for Skeleton-based Vi…

【Linux】自动化构建工具-make/Makefile详解

前言 大家好吖&#xff0c;欢迎来到 YY 滴 Linux系列 &#xff0c;热烈欢迎&#xff01;本章主要内容面向接触过Linux的老铁&#xff0c;主要内容含 欢迎订阅 YY 滴Linux专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 订阅专栏阅读&#xff1a;YY的《…

深度学习——LSTM解决分类问题

RNN基本介绍 概述 循环神经网络&#xff08;Recurrent Neural Network&#xff0c;RNN&#xff09;是一种深度学习模型&#xff0c;主要用于处理序列数据&#xff0c;如文本、语音、时间序列等具有时序关系的数据。 核心思想 RNN的关键思想是引入了循环结构&#xff0c;允许…

什么是剪贴板劫持-剪贴板劫持教程

目录 前言 什么是剪贴板劫持如何避免剪贴板劫持&#xff1f;如何执行剪贴板劫持&#xff1f; 总结 前言 我来写剪贴板劫持教程。 什么是剪贴板劫持 剪贴板劫持是一种危险的攻击技术&#xff0c;借助该攻击者可以控制受害者的剪贴板并将恶意代码粘贴到目标机器中&#xff0c;…

基于单片机的语音识别智能垃圾桶垃圾分类的设计与实现

功能介绍 以51单片机作为主控系统&#xff1b;液晶显示当前信息和状态&#xff1b;通过语音识别模块对当前垃圾种类进行语音识别&#xff1b; 通过蜂鸣器进行声光报警提醒垃圾桶已满&#xff1b;采用舵机控制垃圾桶打开关闭&#xff1b;超声波检测当前垃圾桶满溢程度&#xff1…

认识spring项目的创建 和 从spring中进行Bean对象的存取

前言 本篇简单介绍如何创建spring项目&#xff0c;如何存储到spring容器中&#xff0c;如何从容器中获取Bean对象&#xff0c;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&#xff01; 文章目录 前言1. 创建spring项目2. 将Bean对象存…

RS485/RS232自由转ETHERNET/IP网关rs485和232接口一样吗

你是否曾经遇到过这样的问题&#xff1a;如何将ETHERNET/IP网络和RS485/RS232总线连接起来呢&#xff1f; 远创智控的YC-EIP-RS485/232通讯网关&#xff0c;自主研发的ETHERNET/IP从站功能&#xff0c;完美解决了这个难题。这款网关不仅可以将ETHERNET/IP网络和RS485/RS232总线…

服务器数据恢复-ESX SERVER无法连接到STORAGE的数据恢复案例

服务器数据恢复环境&#xff1a; 某公司信息管理平台&#xff0c;数台VMware ESX SERVER虚拟机共享一台IBM某型号存储。 服务器故障&#xff1a; VC报告虚拟磁盘丢失&#xff0c;管理员ssh到ESX中执行fdisk -l命令查看磁盘&#xff0c;发现STORAGE已经没有分区表了。重启设备后…