剑指Offer13.机器人的运动范围 C++

1、题目描述

  • 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
  • 示例 1
    输入:m = 2, n = 3, k = 1
    输出:3
  • 示例 2
    输入:m = 3, n = 1, k = 0
    输出:1

2、VS2019上运行

使用方法一:广度优先搜索BFS

#include <iostream>
#include <vector>
#include <queue>
using namespace std;class Solution {// 计算 x 的数位之和int get(int x) {int res = 0;for (; x; x /= 10) {res += x % 10;}return res;}
public:int movingCount(int m, int n, int k) {if (!k) return 1;queue<pair<int, int> > Q;//队列Q用于存储待访问的格子数量,第一个表示横坐标,第二个表示纵坐标// 向右和向下的方向数组//以向右(x轴正方向)和向下(y轴正方向)移动为例。int dx[2] = { 0, 1 };int dy[2] = { 1, 0 };//创建一个二维矩阵 vis,用于记录矩阵中每个位置是否已经被访问过。//初始时,所有位置都被标记为未访问(0)。vector<vector<int> > vis(m, vector<int>(n, 0));//m行n列,全部元素设为0//向队列 Q 中插入一个整数对作为元素。这里是将 (0, 0) 作为起始位置插入到队列中Q.push(make_pair(0, 0));vis[0][0] = 1;//将矩阵 vis 中坐标 (0, 0) 的元素设置为 1,表示该位置已被访问。int ans = 1;//变量 ans 用于记录满足特定条件的位置数量while (!Q.empty()) {// 取出队首的格子位置pair<int, int> front = Q.front();Q.pop();//将整数对 front 中的第一个元素和第二个元素分别存储到变量 x 和 y 中。也就是横坐标和纵坐标int x = front.first;int y = front.second;for (int i = 0; i < 2; ++i) {//循环遍历一个长度为2的数组,右和下int tx = dx[i] + x;//计算出下一个横坐标int ty = dy[i] + y;//计算下一个纵坐标// 判断下一个位置是否满足限制条件if (tx < 0 || tx >= m || ty < 0 || ty >= n || vis[tx][ty] || get(tx) + get(ty) > k) continue;Q.push(make_pair(tx, ty));//将计算出的下一个位置 (tx, ty) 插入到队列 Q 中,作为待访问的位置。vis[tx][ty] = 1;//该位置已访问ans++;}}return ans;}
};
int main() {int m = 2, n = 3, k = 1;Solution sol;int result = sol.movingCount(m, n, k);cout << result << endl;return 0;
}

3

3、解题思路

  • 这段代码是解决一个问题:给定一个 m × n 的矩阵,矩阵中的每个位置代表一个格子。现在有一个机器人位于矩阵的左上角,机器人可以向右或向下移动,但不能移动到数位之和大于 k 的格子。请问,机器人能够到达多少个格子?
    具体的解决思路如下:
  • 1.定义一个函数 get(int x),用来计算数位之和。该函数通过循环将数字 x 每一位上的数字相加,返回数位之和。
  • 2.在 movingCount 函数中,首先判断特殊情况,如果 k 为 0,表示没有限制,机器人可以到达任意位置,所以直接返回 1。
  • 3.创建一个队列 Q,用于存储待访问的格子位置。队列中的每个元素都是一个整数对,表示格子的横坐标和纵坐标。
  • 4.创建两个方向数组 dx 和 dy,用来表示向右和向下移动的偏移量。
  • 5.创建一个二维矩阵 vis,用于记录矩阵中的每个位置是否已经被访问过。初始时,所有位置都被标记为未访问(0)。
  • 6.将起始位置 (0, 0) 插入到队列 Q 中,并将矩阵 vis 中对应的位置设为已访问(1)。
  • 7.定义变量 ans,初始值为 1,用于记录满足限制条件的位置数量。
  • 8.使用广度优先搜索算法,不断遍历队列 Q 中的格子位置,进行下一步移动的判断。
  • 9.在遍历的过程中,取出队列头部的格子位置,并将其分别存储到变量 x 和 y 中。
  • 10.循环遍历方向数组 dx 和 dy 中的元素,分别计算出下一个位置的横坐标 tx 和纵坐标 ty。
  • 11.判断下一个位置是否越界、已经访问过、或数位之和大于 k。如果满足其中任一条件,跳过当前循环,进行下一次循环。
  • 12.如果下一个位置满足限制条件,将其插入队列 Q 中作为待访问的位置,并将矩阵 vis 中对应的位置设为已访问(1)。
  • 13.将计数器 ans 递增,表示发现了一个满足条件的位置。
  • 14.当队列 Q 中的格子位置全部遍历完毕时,返回 ans,即满足条件的位置数量。
  • 整体思路是通过广度优先搜索算法遍历满足条件的位置,并使用一个队列和一个二维矩阵分别记录待访问的位置和已访问的位置。算法的时间复杂度为 O(m * n),其中 m 和 n 分别表示矩阵的行数和列数。

4、get函数

  // 计算 x 的数位之和int get(int x) {int res = 0;for (; x; x /= 10) {res += x % 10;}return res;}
  • 这段代码定义了一个名为 get 的函数,它的作用是计算一个整数 x 的数位之和。
  • 首先,变量 res 被初始化为 0,用于保存数位之和的结果。
  • 然后,通过一个 for 循环,循环的条件是 x 不为0,循环体内执行 x = x / 10,即将 x 除以 10,这样可以实现依次取 x 的个位、十位、百位等。
  • 在每次循环中,通过 x % 10 取出 x 的个位数,然后将它加到 res 变量上。
  • 最后,当循环结束时,函数返回 res,即计算得到的数位之和。
  • 例如,如果 x 的值为 12345,那么这个函数将返回的数位之和为 1 + 2 + 3 + 4 + 5 = 15。

5、queue<pair<int, int> > Q

  • 这行代码声明了一个名为 Q 的队列变量,用于存储格子的位置信息。
  • Q 是一个队列,每个队列元素都是一个二维坐标的整数对,表示矩阵中的某个格子的位置。
  • pair<int, int> 表示一个这样的二维坐标对,其中第一个整数表示横坐标,第二个整数表示纵坐标。
  • 这样定义的队列 Q 可以用来保存待访问的格子位置,通常在广度优先搜索算法中会使用队列来实现。通过队列的先进先出特性,可以实现按照一定顺序逐步处理格子位置,从而完成搜索或遍历操作。

6、 vector<vector > vis(m, vector(n, 0));

  • 这行代码声明了一个二维矩阵变量 vis,用于记录矩阵中每个位置的访问状态。
  • vis 是一个二维的 vector,其中第一维表示矩阵的行数 m,第二维表示矩阵的列数 n。这样定义的二维矩阵 vis 有 m 行、n 列。
  • vector<int>(n, 0) ,为每一行创建一个内部向量,创建一个包含 n 个元素的整数型向量,并将每个元素的初始值设置为0。这样创建的向量将被用作矩阵 vis 的每一行,用于表示对应位置的访问状态。
  • 在 vector<int>(n, 0) 中,vector<int> 表示创建一个整数型向量,(n, 0) 是一个构造函数的参数,指定了向量的大小为 n,且将每个元素初始化为0。最终得到的向量将作为矩阵 vis 的一行。
  • 在该算法中,vis 矩阵用于记录矩阵中每个位置的访问状态。当一个位置被访问时,对应位置的值会被设置为1,表示已经访问过。这在广度优先搜索等算法中很常见,可以避免重复访问同一个位置。

7、for (int i = 0; i < 2; ++i) {};

  • 循环遍历一个长度为2的数组是为了考虑当前位置 (x, y) 的相邻位置。
  • 在给定的代码中,循环遍历的是长度为2的数组 [0, 1]。这是因为在二维矩阵中,我们通常只需要考虑横向和纵向的相邻位置,即上方、下方、左侧和右侧位置。这个数组的两个元素 [0, 1] 分别表示在横向和纵向上的移动方式。

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

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

相关文章

SpringMVC的架构有什么优势?——表单和数据校验(四)

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

记录一次前端input中的值为什么在后端取不到值

前端源码&#xff1a; <input type"text" name"user" placeholder"请输入你的名字" class"layui-input" value"{{ username}}" size"50" disabled"true"> 后端源码&#xff1a; send_name req…

深度学习(37)—— 图神经网络GNN(2)

深度学习&#xff08;37&#xff09;—— 图神经网络GNN&#xff08;2&#xff09; 这一期主要是一些简单示例&#xff0c;针对不同的情况&#xff0c;使用的数据都是torch_geometric的内置数据集 文章目录 深度学习&#xff08;37&#xff09;—— 图神经网络GNN&#xff08…

list模拟实现【引入反向迭代器】

文章目录 1.适配器1.1传统意义上的适配器1.2语言里的适配器1.3理解 2.list模拟实现【注意看反向迭代器】2.1 list_frame.h2.2riterator.h2.3list.h2.4 vector.h2.5test.cpp 3.反向迭代器的应用1.使用要求2.迭代器的分类 1.适配器 1.1传统意义上的适配器 1.2语言里的适配器 容…

基于python+MobileNetV2算法模型实现一个图像识别分类系统

一、目录 算法模型介绍模型使用训练模型评估项目扩展 二、算法模型介绍 图像识别是计算机视觉领域的重要研究方向&#xff0c;它在人脸识别、物体检测、图像分类等领域有着广泛的应用。随着移动设备的普及和计算资源的限制&#xff0c;设计高效的图像识别算法变得尤为重要。…

fork函数和exec族函数的结合使用 的案例

首先回顾之前所讲&#xff0c;在说明“为什么要创建进程”的时候&#xff0c;提到过以下两个原因&#xff1a; 其中第一个原因很好理解&#xff0c;而第二个原因就包含了上节所讲的exec族函数的知识点&#xff0c;并且不管是之前的博文还是上节的exec&#xff0c;都提到了一点“…

重启服务器引发的Docker异常

公司使用云服务器需要硬盘扩容&#xff0c;服务器重启才生效。 重启以后发现拉取远程镜像的命令登录失败了&#xff01; 然后发现找不到容器和镜像列表了&#xff0c;但是容器都启动了。 查看docker运行状态都是正常的 systemctl is-active docker systemctl status docker.…

爬虫015_python异常_页面结构介绍_爬虫概念介绍---python工作笔记034

来看python中的异常 可以看到不做异常处理因为没有这个文件所以报错了 来看一下异常的写法

exec族函数

本节学习exec族函数&#xff0c;并大量参考了以下链接&#xff1a; linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客 exec族函数函数的作用 我们用fork函数创建新进程后&#xff0c;经常会在新进程中调用exec函数去执行另外一个程…

Fortinet安全专家问答实录|如何防护暴力破解、撞库攻击

黑客攻防&#xff0c;一个看似神秘&#xff0c;但却必不可缺的领域。近期&#xff0c;全球网络与安全融合领域领导者Fortinet&#xff08;Nasdaq&#xff1a;FTNT&#xff09;&#xff0c;开启了Fortinet DEMO DAY系列实战攻防演练线上直播&#xff0c;让人人都能零距离观摩黑客…

AI 绘画Stable Diffusion 研究(六)sd提示词插件

大家好&#xff0c;我是风雨无阻。 今天为大家推荐一款可以有效提升我们使用 Stable Diffusion WebUI 效率的插件&#xff0c; 它就是 prompt-all-in-one&#xff0c; 它不但能直接将 WebUI 中的中文提示词转换为英文&#xff0c;还能一键为关键词加权重&#xff0c;更能建立常…

消息中间件 —— 初识Kafka

文章目录 1、Kafka简介1.1、消息队列1.1.1、为什么要有消息队列&#xff1f;1.1.2、消息队列1.1.3、消息队列的分类1.1.4、p2p 和 发布订阅MQ的比较1.1.5、消息系统的使用场景1.1.6、常见的消息系统 1.2、Kafka简介1.2.1、简介1.2.2、设计目标1.2.3、kafka核心的概念 2、Kafka的…

存储过程的学习

1&#xff0c;前言 这是实习期间学习的&#xff0c;我可能是在学校没好好听课&#xff0c;&#xff08;或者就是学校比较垃&#xff0c;没教这部分&#xff0c;在公司经理让我下去自己学习&#xff0c;太难了&#xff0c;因为是公司代码很多部分都是很多表的操作&#…

菲律宾的区块链和NFT市场调研

菲律宾的区块链和NFT市场调研 基本介绍 参考&#xff1a; https://zh.wikipedia.org/wiki/%E8%8F%B2%E5%BE%8B%E5%AE%BE zheng治制度&#xff1a;Zongtong议会制 现任Zongtong&#xff1a; 小费迪南德马科斯, 是独裁者费迪南德马科斯之子&#xff0c;人称“小马科斯” 官方语言…

【动态map】牛客挑战赛67 B

登录—专业IT笔试面试备考平台_牛客网 题意&#xff1a; 思路&#xff1a; 考虑动态的map 可以先定义一个状态&#xff0c;然后用map统计前缀这个状态的出现次数 在这里&#xff0c;定义{a,b}为cnt1 - cnt0和cnt2 - cnt0 当cnt0 和 cnt1都和cnt2相同时&#xff0c;统计贡献…

Linux进程之调度器

1. Linux调度器的原理 Linux调度器(Linux Scheduler)负责管理这一进程在CPU上运行时的资源分配。它根据选定策略和所估算的进程行为,考量各种因素的权重,对等待在运行队列的进程按优先级排列,从而决定哪个进程能够接下来获得CPU时间。 Linux的调度器可以使用不同的调度策…

oracle 增加控制文件

oracle 增加控制文件 1、看control_file路径 SQL> show parameter controlNAME TYPE VALUE ------------------------------------ ----------- ------------------------------ control_file_record_keep_time integer …

Kubernetes kubectl管理命令使用方法

陈述式资源管理方法&#xff08;通过命令行&#xff09; 1.kubernetes 集群管理集群资源的唯一入口是通过相应的方法调用 apiserver 的接口 2.kubectl 是官方的CLI命令行工具&#xff0c;用于与 apiserver 进行通信&#xff0c;将用户在命令行输入的命令&#xff0c;组织并转化…

[Python进阶] 定制类:运算篇

4.10.4 运算篇 Python的类型系统是鸭子类型&#xff0c;也就是不检查某个具体的对象是什么类型&#xff0c;而是检查这个对象有没有相应的功能。在Python中有大量的魔术方法&#xff0c;我们可以通过魔术方法的方式为对象添加相应的功能。 下面介绍Python中和运算相关的魔术方…

从零开始学python(十六)爬虫集群部署

前言 今天讲述Python框架源码专题最后一个部分&#xff0c;爬虫集群部署&#xff0c;前面更新了十五个从零开始学python的系列文章&#xff0c;分别是&#xff1a; 1.编程语法必修篇 2.网络编程篇 3.多线程/多进程/协程篇 4.MySQL数据库篇 5.Redis数据库篇 6.MongoDB数据库篇 …