每日一题——迷宫问题(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中的模块、对象来处理…

Java设计模式-单例模式

单例模式 1.单例模式含义 单例模式就是保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 其实单例模式很好理解&#xff0c;当我们new一个对象实例的时候&#xff0c;这个对象会被放到一个内存中&#xff0c;当我们再次new同一个对象的实例的时候&#xf…

ES6模块化与异步编程高级用法

目录 ES6 模块化 1、什么是 ES6 模块化规范 2、在 node.js 中体验 ES6 模块化 3、ES6 模块化的基本语法 Promise 1. 回调地狱 2、Promise 的基本概念 3、基于回调函数按顺序读取文件内容 4.、基于 then-fs 读取文件内容 4.1 then-fs 的基本使用 4.2 .then() 方法的特…

ZooKeeper原理剖析

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

SSH客户端连接远程服务器

目录 一、什么是客户端连接远程服务器 二、什么是服务端连接远程服务器 三、查看网络信息 1、图形程序查看网络信息 2、命令查看网络信息 四、SSH客户端&#xff08;Linux&#xff09; 五、SSH客户端&#xff08;windows&#xff09; 六、SSH远程服务器 一、什么是客户…

75、简述你对RPC、RMI的理解

简述你对RPC、RMI的理解 RPC&#xff1a;在本地调用远程的函数&#xff0c;远程过程调用&#xff0c;可以跨语言实现 httpClient RMI&#xff1a;远程方法调用&#xff0c;java中用于实现RPC的一种机制&#xff0c;RPC的java版本&#xff0c;是J2EE的网络调用机制&#xff0c…

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…

jQuery.print打印插件的使用方法

网站新闻内容页面&#xff0c;想只打印新闻内容区域&#xff0c;其他区域不打印&#xff0c;使用了jQuery.print插件&#xff0c;插件下载地址&#xff1a;GitHub - DoersGuild/jQuery.print: Easy to use, Element Printing Plugin for jQuery 插件下载地址&#xff1a;https:…

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;市占率及变化趋势 热销车型&…

OBS 基础 之 使用到的坐标体系 及转换

目录 一、画布坐标 1、画布宽高 2、设置LOGO位置 二、预览窗口坐标

python多线程排查

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

【Rust 基础篇】Rust 多线程:并发编程的艺术

导言 多线程是现代计算机编程中的重要概念&#xff0c;它允许程序同时执行多个任务&#xff0c;充分利用多核处理器的性能优势。在 Rust 中&#xff0c;多线程编程也得到了很好的支持&#xff0c;通过标准库提供的 std::thread 模块可以方便地创建和管理线程。本篇博客将详细介…

vue3+pinia的使用,刷新后不丢数据

前言&#xff1a; 好用的状态管理器&#xff0c;vue3中出来的pinia&#xff0c;相比较vuex来说&#xff0c;更加轻便&#xff0c;使用也更方便。 官方文档&#xff1a;点我 github地址&#xff1a;点我 pinia与vuex相比较优点&#xff1a; pinia 是轻量级状态管理工具&#x…

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…