文章目录

  • 题目描述
  • 解题思路
  • 方法一:深度优先遍历DFS
    • 复杂度分析
    • C++代码实现
  • 方法二:广度优先遍历BFS
    • 复杂度分析
    • C++代码实现
  • 参考连接

题目描述

地上有一个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。请问该机器人能够到达多少个格子?

解题思路

本题与 矩阵中的路径 类似,是典型的搜索 & 回溯问题。该题的两项前置工作为: 数位之和计算可达解分析
数位之和计算:
设一数字 x x x ,向下取整除法符号 / / // // ,求余符号 ⊙ \odot ⊙,则有:

  • x ⊙ 10 x \odot 10 x⊙10 :得到 x x x 的个位数字;
  • x / / 10 x // 10 x//10 : 令 x x x 的十进制数向右移动一位,即删除个位数字。

因此,可通过循环求得数位和 s s s ,数位和计算的封装函数如下所示:

int sums(int x){int s = 0;while(x != 0) {s += x % 10;x = x / 10;}return s;
}

由于机器人每次只能移动一格(即只能从 x x x 运动至 x ± 1 x \pm 1 x±1),因此每次只需计算 x x x 到 x ± 1 x \pm 1 x±1 的数位和增量。本题说明 1 ≤ n 1 \leq n 1≤n, m ≤ 100 m \leq 100 m≤100 ,以下公式仅在此范围适用。
数位和增量公式: 设 x x x 的数位和为 s x s_x sx​ , x + 1 x+1 x+1 的数位和为 s x + 1 s_{x+1} sx+1​ ;

  1. 当 ( x + 1 ) ⊙ 10 = 0 (x + 1) \odot 10 = 0 (x+1)⊙10=0 时: s x + 1 = s x − 8 s_{x+1} = s_x - 8 sx+1​=sx​−8,例如 19 , 20 19, 20 19,20 的数位和分别为 10 , 2 10, 2 10,2 ;
  2. 当 ( x + 1 ) ⊙ 10 ≠ 0 (x + 1) \odot 10 \neq 0 (x+1)⊙10​=0 时: s x + 1 = s x + 1 s_{x+1} = s_x + 1 sx+1​=sx​+1 ,例如 1 , 2 1, 2 1,2 的数位和分别为 1 , 2 1, 2 1,2 。

可达解分析:
根据数位和增量公式得知,数位和每逢 进位 突变一次。根据此特点,矩阵中 满足数位和的解 构成的几何形状形如多个 等腰直角三角形 ,每个三角形的直角顶点位于 0 , 10 , 20 , . . . 0, 10, 20, ... 0,10,20,... 等数位和突变的矩阵索引处 。
三角形内的解虽然都满足数位和要求,但由于机器人每步只能走一个单元格,而三角形间不一定是连通的,因此机器人不一定能到达,称之为 不可达解 ;同理,可到达的解称为 可达解
根据可达解的结构和连通性,易推出机器人可 仅通过向右和向下移动,访问所有可达解

  • 三角形内部: 全部连通,易证;
  • 两三角形连通处: 若某三角形内的解为可达解,则必与其左边或上边的三角形连通(即相交),即机器人必可从左边或上边走进此三角形。

方法一:深度优先遍历DFS

  • 深度优先搜索: 可以理解为暴力法模拟机器人在矩阵中的所有路径。DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
  • 剪枝: 在搜索中,遇到数位和超出目标值、此元素已访问,则应立即返回,称之为 可行性剪枝

算法解析

  • 递归参数: 当前元素在矩阵中的行列索引 i i i 和 j j j ,两者的数位和 s i si si, s j sj sj 。

  • 终止条件: 当 ① ① ① 行列索引越界 ② ② ② 数位和超出目标值 k k k ③ ③ ③ 当前元素已访问过时,返回 0 0 0 ,代表不计入可达解。

  • 递推工作:
    1.标记当前单元格:将索引 ( i , j ) (i, j) (i,j) 存入 visited 中,代表此单元格已被访问过。
    2.搜索下一单元格: 计算当前元素的 下、右 两个方向元素的数位和,并开启下层递归。

  • 回溯返回值: 返回 1 + 右方搜索的可达解总数 + 下方搜索的可达解总数,代表从本单元格递归搜索的可达解总数。

复杂度分析

  • 时间复杂度 O ( M N ) O(MN) O(MN) : 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O ( M N ) O(MN) O(MN)。
  • 空间复杂度 O ( M N ) O(MN) O(MN) : 最差情况下,visited 内存储矩阵所有单元格的索引,使用 O ( M N ) O(MN) O(MN) 的额外空间。

C++代码实现

class Solution {public:int movingCount(int m, int n, int k) {vector<vector<bool>> visited(m, vector<bool>(n, 0));return dfs(0, 0, 0, 0, visited, m, n, k);}
private:int dfs(int i, int j, int si, int sj, vector<vector<bool>> &visited, int m, int n, int k) {// 如果不符合条件则直接返回0if(i >= m || j >= n || k < si + sj || visited[i][j]) return 0;// 该位置被访问并记录visited[i][j] = true;// 向下和向右进行搜索return 1 + dfs(i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj, visited, m, n, k) +dfs(i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8, visited, m, n, k);}
};

方法二:广度优先遍历BFS

  • BFS/DFS: 两者目标都是遍历整个矩阵,不同点在于搜索顺序不同。DFS 是朝一个方向走到底,再回退,以此类推;BFS 则是按照“平推”的方式向前搜索。
  • BFS 实现: 通常利用队列实现广度优先遍历。

算法解析:

  • 初始化: 将机器人初始点 ( 0 , 0 ) (0, 0) (0,0) 加入队列 q u e u e queue queue ;
  • 迭代终止条件: q u e u e queue queue 为空。代表已遍历完所有可达解。
  • 迭代工作:
    1.单元格出队: 将队首单元格的 索引、数位和 弹出,作为当前搜索单元格。
    2.判断是否跳过: 若 ① ① ① 行列索引越界 ② ② ② 数位和超出目标值 k k k ③ ③ ③ 当前元素已访问过 时,执行 c o n t i n u e continue continue 。
    3.**标记当前单元格 :**将单元格索引 ( i , j ) (i, j) (i,j) 存入 visited 中,代表此单元格 已被访问过
    4.单元格入队: 将当前元素的 下方、右方 单元格的 索引、数位和 加入 q u e u e queue queue 。
  • 返回值: visited 的长度 len(visited) ,即可达解的数量。

复杂度分析

  • 时间复杂度 O ( M N ) O(MN) O(MN): 最差情况下,机器人遍历矩阵所有单元格,此时时间复杂度为 O ( M N ) O(MN) O(MN) 。
  • 空间复杂度 O ( M N ) O(MN) O(MN): 最差情况下,visited 内存储矩阵所有单元格的索引,使用 O ( M N ) O(MN) O(MN) 的额外空间。

C++代码实现

class Solution {public:int movingCount(int m, int n, int k) {vector<vector<bool>> visited(m, vector<bool>(n, 0));int res = 0;queue<vector<int>> que;que.push({ 0, 0, 0, 0 });while(que.size() > 0) {vector<int> x = que.front();que.pop();int i = x[0], j = x[1], si = x[2], sj = x[3];if(i >= m || j >= n || k < si + sj || visited[i][j]) continue;visited[i][j] = true;res++;que.push({ i + 1, j, (i + 1) % 10 != 0 ? si + 1 : si - 8, sj });que.push({ i, j + 1, si, (j + 1) % 10 != 0 ? sj + 1 : sj - 8 });}return res;}
};

参考连接

[1] https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/solution/mian-shi-ti-13-ji-qi-ren-de-yun-dong-fan-wei-dfs-b/

Leetcode刷题笔记——剑指 Offer 13. 机器人的运动范围(中等)相关推荐

  1. leetcode刷题笔记——剑指offer(二)[回溯、排序、位运算、数学、字符串]

    这里写目录标题 搜索与回溯 剑指 Offer 12. 矩阵中的路径 剑指 Offer 13. 机器人的运动范围 剑指 Offer 34. 二叉树中和为某一值的路径 剑指 Offer 36. 二叉搜索树 ...

  2. Leetcode刷题笔记——剑指offer II (六)【图】

    文章目录 图 695. 岛屿的最大面积 剑指 Offer II 106. 二分图 (每条边的两个结点都来自不同的集合) 剑指 Offer II 107. 矩阵中的距离 (最短路问题,建图,BFS) 剑 ...

  3. Leetcode刷题笔记——剑指offer II (一)【整数、数组、字符串、链表】

    目录 整数 剑指 Offer II 001. 整数除法 剑指 Offer II 002. 二进制加法 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数 剑指 Offer II 00 ...

  4. Leetcode刷题笔记——剑指offer II (五)【二分、排序、回溯】

    这里写目录标题 二分查找 剑指 Offer II 069. 山峰数组的顶部 剑指 Offer II 070. 排序数组中只出现一次的数字 剑指 Offer II 071. 按权重生成随机数 剑指 Of ...

  5. Leetcode刷题笔记——剑指 Offer 46. 把数字翻译成字符串(中等)

    文章目录 题目描述 解法:动态规划 方法一:字符串遍历 复杂度分析 C++代码实现 方法二:数字求余 复杂度分析 C++代码实现 参考链接 题目描述 给定一个数字,我们按照如下规则把它翻译为字符串:0 ...

  6. 【LeetCode】剑指 Offer 13. 机器人的运动范围

    [LeetCode]剑指 Offer 13. 机器人的运动范围 文章目录 [LeetCode]剑指 Offer 13. 机器人的运动范围 package offer;public class Solu ...

  7. LeetCode 剑指Offer 13 机器人的运动范围

    LeetCode 剑指Offer 13 机器人的运动范围 题目 解题 解题一:深度优先搜索 解题二:广度优先搜索 解题三:动态规划 题目 解题 深度优先和广度优先解题思路参考: 剑指 Offer 13 ...

  8. 剑指 Offer 13. 机器人的运动范围

    剑指 Offer 13. 机器人的运动范围 题目 ​ 地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] .一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左.右.上 ...

  9. [[EVD]] - 剑指 Offer 13. 机器人的运动范围

    题目分析:[[EVD]] - 剑指 Offer 13. 机器人的运动范围https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-l ...

最新文章

  1. python3.9教程_Python3简明教程(九)—— 文件处理
  2. 一维二维_更高效的一维、二维材料过渡态搜索
  3. AC日记——[USACO10MAR]仓配置Barn Allocation 洛谷 P1937
  4. 推荐一款优雅的日历控件
  5. fck2.6.3配置
  6. SpringNote01.基于SpringMVC-Hibernate的Blog系统
  7. Hbase rowkey 设计原则
  8. 军用装备产品GJB150A淋雨试验检测机构
  9. 分析微信聊天记录(1)——获取微信聊天记录
  10. 最齐全的黑防VIP教程,个人认为不错(123课)
  11. vue3获取url后面参数
  12. 荣耀笔记本pro linux版本,荣耀MagicBook Pro锐龙版发布:首发锐龙7 3750H、还有Linux版...
  13. 远程桌面桌面无法找到计算机,Windows – 远程桌面客户端找不到远程计算机
  14. 买二手房不后悔先知道8件事 高楼层未必卖得好
  15. 结构化数据和半结构化数据和非结构化数据
  16. 总结八:面试程序员前需要的准备工作
  17. GDAL 遥感 图像处理 锐化(Laplace算子、Sobel算子)
  18. 学习OpenCV(1)概述
  19. HAproxy正向代理配置
  20. 经典仿句100例_仿写句子_二年级仿写句子100例

热门文章

  1. pdmreader 连接mysql_powerdesigner连接mysql,并导出其数据模型的方法
  2. html+CSS之百度首页练习
  3. 51Nod_1174区间中最大值
  4. 企业信息管理系统(C++)
  5. 移动端设置border的1px像素解决方案
  6. 抓取豆瓣音乐Top 250数据存到Excel中
  7. 微信小程序 为input绑定回车事件
  8. MySQL 笔记 —— 时间函数、时间比较
  9. 【精】进阶教程!让视觉设计变得高效+有说服力的4个步骤
  10. python中代码块所属关系的语法_pythony语法元素