35.机器人的运动范围(medium)

1.题目链接:LCR 130. 衣橱整理 - 力扣(LeetCode)LCR 130. 衣橱整理 - 家居整理师将待整理衣橱划分为 m x n 的二维矩阵 grid,其中 grid[i][j] 代表一个需要整理的格子。整理师自 grid[0][0] 开始 逐行逐列 地整理每个格子。整理规则为:在整理过程中,可以选择 向右移动一格 或 向下移动一格,但不能移动到衣柜之外。同时,不需要整理 digit(i) + digit(j) > cnt 的格子,其中 digit(x) 表示数字 x 的各数位之和。请返回整理师 总共需要整理多少个格子。 示例 1:输入:m = 4, n = 7, cnt = 5输出:18 提示: * 1 <= n, m <= 100 * 0 <= cnt <= 20 https://leetcode.cn/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/description/

2.题目描述:

地上有一个 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

3. 算法思路:
这是一道非常典型的「搜索」类问题。

我们可以通过「深搜」或者「宽搜」,从 [0, 0]  点出发,按照题目的「规则」一直往 [m - 1, n - 1]  位置走。​
同时,设置一个全局变量。每次走到一个合法位置,就将全局变量加一。当我们把所有能走到的路都走完之后,全局变量里面存的就是最终答案。

4. 解法(dfs):​
算法流程:

递归函数设计:

a. 参数:当前所在的位置 [i, j] ,行走的边界 [m, n] ,坐标数位之和的边界 k ;​b. 递归出口:​

i.

[i, j]  的坐标不合法,也就是已经超出能走的范围;​

ii.

[i, j]  位置已经走过了(因此我们需要创建一个全局变量 bool st[101][101]

来标记当前位置是否走过);

iii.

[i, j]  坐标的数位之和大于 k ;​

上述情况的任何一种都是递归出口。

c. 函数体内部:

i.

如果这个坐标是合法的,就将全局变量 ret++ ;​

ii. 然后标记一下 [i, j]  位置已经遍历过;​

iii. 然后去 [i, j]  位置的上下左右四个方向去看看。​

辅助函数:

a. 检测坐标 [i, j]  是否合法;​

b. 计算出 ij  的数位之和,然后与 k  作比较即可。​

主函数:

a. 调用递归函数,从 [0 ,0]  点出发。​

辅助的全局变量:

a. 二维数组 bool st[101][101] :标记 [i, j]  位置是否已经遍历过;​

b. 变量 ret  :记录一共到达多少个合法的位置。​

c. 上下左右的四个坐标变换。

Java算法代码:

class Solution {
    int m,n,k;
    boolean[][] vis;
    int [] dx = {1,-1,0,0};
    int [] dy = {0,0,1,-1};
    int ret;

    public int wardrobeFinishing(int _m, int _n, int _k) {
        m = _m; n = _n; k = _k;
        vis = new boolean[m][n];
        dfs(0,0);
        return ret;

    }
    public void dfs(int i, int j){
        ret++;
        vis[i][j] = true;
        for(int k = 0;k<4;k++){
            int x = i + dx[k], y = j + dy[k];
            if(x>= 0 && x < m && y>= 0 && y < n && !vis[x][y] && check(x,y))
                dfs(x,y);
        }
    }
    public boolean check(int i, int j){
        int tmp = 0;
        while( i != 0){
            tmp += i %10;
            i /= 10;
        }
        while(j != 0){
            tmp += j%10;
            j /= 10;
        }
        return tmp <= k;
    }
}

运行结果:

递归展开:

这道题的重点是理解题干(知道check这个方法怎么写出来的就行)

逻辑展开:

直接根据 下, 上,右,左的顺序来人工手动遍历。

---------------------------------------------------------------------------------------------------------------------------------

记住,相信你的递归函数,它可以做到!

记住,不理解时候,去尝试手动展开!

记住,逻辑展开(你不可能对所有的题目都进行手动展开)!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值