《剑指offer》刷题系列——(五十七)机器人的运动范围

题目

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

示例 :
输入:m = 2, n = 3, k = 1
输出:3

思路

本题与 矩阵中的路径 题目有相似之处,是典型的搜索问题,可以用递归实现的深度优先解决。

递归需要用到状态或者子问题的概念。
方格可看成m*n的矩阵。假设当前坐标为(i,j),那么问题转化为从(i,j)出发,机器人最多能到达多少个格子。
构造子问题:
根据机器人的运动规则,机器人从(i,j)出发,能够到达(i+1,j),(i-1,j),(i,j+1),(i,j-1)四个位置。子问题是,机器人从上面这四个方向出发,分别能到达多少个格子。如果求出子问题的解,然后将它们全部整合起来再加1就得到了原问题的解。加1的原因是包含当前(i,j)这个格子。

对于矩阵搜索,需要定义一个二维矩阵来记录当前格子是否被访问过,一旦访问过,说明该格子已经包含在子问题中,需要返回0,避免重复计算。

深度优先搜索的返回条件:
1、下标越界
2、已经访问过该格子
3、该格子行坐标和列坐标的数位之和大于k

代码

class Solution:
    def movingCount(self, m: int, n: int, k: int) -> int:
        visit = [[False for _ in range(n)] for _ in range(m)]
        res = self.dfs(0,0,m,n,k,visit)
        return res

    def sum_digit(self,digit):
        s = 0
        while digit:
            s += digit % 10
            digit //=10
        return s
    
    def dfs(self,i,j,m,n,k,visit):
        if i<0 or j<0 or i>=m or j>=n:
            return 0
        if self.sum_digit(i)+self.sum_digit(j)>k:
            return 0
        if visit[i][j]==1:
            return 0
        visit[i][j]=True
        return 1+self.dfs(i-1,j,m,n,k,visit)+self.dfs(i+1,j,m,n,k,visit)+self.dfs(i,j-1,m,n,k,visit)+self.dfs(i,j+1,m,n,k,visit)

复杂度

时间复杂度:O(mn)
空间复杂度:O(mn)

知识点

在python中,
" / " 表示浮点数除法,返回浮点结果;
" // " 表示整数除法,返回不大于结果的一个最大的整数。

猜你喜欢

转载自blog.csdn.net/weixin_44776894/article/details/107458543
今日推荐