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
提示:
1 <= n,m <= 100
0 <= k <= 20
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof
2. 思路分析:
① 由题目可以知道这道题目与之前的力扣中二维方格中关于路径的题目是类似的,只是两者求解的变量和限制的条件是不一样的,但是求解的思路是类似的,只是在细节处理上有所不同。对于这种在二维方格中行走的问题经典的做法是dfs,使用dfs可以搜索所有可能到达的位置,这也与我们要求解的能够到达的所有位置的目标是一致的,对于这道题目来说可以定义一个全局变量,当我们每调用一次dfs说明可以到达的位置会多一个,所以在dfs方法的一开始对这个全局变量计数加1即可,因为涉及到上下左右四个方向,所以我们可以定义一个二维列表,遍历列表中的四个方向,对于当前的位置(x,y)尝试四个方向看是否可以到达,可以到达的前提是新的位置(x1,y1)不超出格子的边界,之前还没有访问过这个格子,并且(x1,y1)中x1,y1各个位置上的数字和不超出k即可搜索下一个位置,也就是递归下一个位置
② 因为是在二维列表中搜索,所以为了避免重复访问同一个位置的问题使用set集合来标记之前已经访问过的位置,我们可以在dfs方法的一开始就将当前位置(x,y)加入到这个set集合中就可以了,整个思路还是挺好理解的,而且对于这种问题使用dfs方法求解基本上就是上面这些套路,其中涉及的问题主要是边界上的判断,题目的限制条件
3. 代码如下:
from typing import List
class Solution:
count = 0
# 计算两个数字各个位上的和
def cal(self, m: int, n: int):
sum = 0
while m:
sum += m % 10
m //= 10
while n:
sum += n % 10
n //= 10
return sum
def dfs(self, m: int, n: int, k: int, x: int, y: int, pos: List[List[int]], rec: set) -> int:
# 将递归的位置加入到set集合中标记已经访问过这个位置
rec.add((x, y))
self.count += 1
# 使用一个二维列表表示上下左右四个方向
for i in range(4):
x1, y1 = x + pos[i][0], y + pos[i][1]
if 0 <= x1 < m and 0 <= y1 < n and (x1, y1) not in rec:
if self.cal(x1, y1) <= k:
self.dfs(m, n, k, x1, y1, pos, rec)
def movingCount(self, m: int, n: int, k: int) -> int:
pos = [[0, 1], [0, -1], [1, 0], [-1, 0]]
self.dfs(m, n, k, 0, 0, pos, set())
return self.count