(java)机器人的运动范围:地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当


题目描述

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

我的分析

【用例没通过,只是分享思路,希望大家一起交流】
找规律:我们把方格看成是一个矩阵,矩阵最左下角的为(0,0),那么矩阵最右上角的数位之和就为最大
举个例子:
[ ( 0 , 7 ) ( 1 , 7 ) ( 2 , 7 ) ( 3 , 7 ) ( 0 , 6 ) ( 1 , 6 ) ( 2 , 6 ) ( 3 , 6 ) ( 0 , 5 ) ( 1 , 5 ) ( 2 , 5 ) ( 3 , 5 ) ( 0 , 4 ) ( 1 , 4 ) ( 2 , 4 ) ( 3 , 4 ) ( 0 , 3 ) ( 1 , 3 ) ( 2 , 3 ) ( 3 , 3 ) ( 0 , 2 ) ( 1 , 2 ) ( 2 , 2 ) ( 3 , 2 ) ( 0 , 1 ) ( 1 , 1 ) ( 2 , 1 ) ( 3 , 1 ) ( 0 , 0 ) ( 1 , 0 ) ( 2 , 0 ) ( 3 , 0 ) ] \left[ \begin{matrix}{} \left( 0,7 \right)& \left( 1,7 \right)& \left( 2,7 \right)& \left( 3,7 \right)\\ \left( 0,6 \right)& \left( 1,6 \right)& \left( 2,6 \right)& \left( 3,6 \right)\\ \left( 0,5 \right)& \left( 1,5 \right)& \left( 2,5 \right)& \left( 3,5 \right)\\ \left( 0,4 \right)& \left( 1,4 \right)& \left( 2,4 \right)& \left( 3,4 \right)\\ \left( 0,3 \right)& \left( 1,3 \right)& \left( 2,3 \right)& \left( 3,3 \right)\\ \left( 0,2 \right)& \left( 1,2 \right)& \left( 2,2 \right)& \left( 3,2 \right)\\ \left( 0,1 \right)& \left( 1,1 \right)& \left( 2,1 \right)& \left( 3,1 \right)\\ \left( 0,0 \right)& \left( 1,0 \right)& \left( 2,0 \right)& \left( 3,0 \right)\\ \end{matrix} \right] (0,7)(0,6)(0,5)(0,4)(0,3)(0,2)(0,1)(0,0)(1,7)(1,6)(1,5)(1,4)(1,3)(1,2)(1,1)(1,0)(2,7)(2,6)(2,5)(2,4)(2,3)(2,2)(2,1)(2,0)(3,7)(3,6)(3,5)(3,4)(3,3)(3,2)(3,1)(3,0)

  • 若k 大于 矩阵最右上角的值,说明矩阵中最大的数位之和都比k小,那么其他的也小于,所以机器人能到达矩阵的全部格子
  • 若k 小于 矩阵中最大的数位之和 大于 矩阵最长边数位之和的最小值(矩阵左上角),机器人所能到达的格子是矩阵左上角数位之和为k+1的全部格子再减1 ,在例子中,假设k=8,那么机器人所能到达的格子是以(2,7)为最右上角的全部格子再减去(2,7)
  • 若k 小于 矩阵最长边数位之和的最小值 大于 矩阵最短边的数位之和的最大值,机器人所能到达的格子是以最短边为边长的正方形再加上一个下三角矩阵,在例子中,假设k=4,机器人所能到达的格子就是以最短边为4,顶点为(3,0)的正方形矩阵再加上一个以最左下角位置为(0,3),由(0,4)(0,3)(1,3)所形成的下三角矩阵
  • 若k 小于 矩阵最短边的数位之和的最大值还要小,那么其实机器人能到达的格子就是由k来决定的,就是算一个上三角或者下三角,用等差数列求和公式,在例子中,假设k=2,机器人所能到达的格子是以最左下角位置为(0,0),由(0,2)(0,1)(1,1)(0,0)(1,0)(2,0)

我的代码

/**
 * 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,
 * 每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。
 * 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。
 * 但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
 */
public class Solution {
    public int movingCount(int threshold, int rows, int cols)
    {
        int min = Min(cols,rows);
        int max = Max(cols,rows);
        if (rows == 0 || cols == 0) return 0;
        if (threshold == 0) return 1;//这时已经排除了rows或cols为0的情况
        if (threshold>((sumNum(rows-1)+sumNum(cols-1)))){
            //若最右上角的数位之和小于threshold,说明最大的都比threshold小,那么其他的也小于
            return rows*cols;
        }
        if (threshold<((sumNum(rows-1)+sumNum(cols-1)))&&(threshold>(Max(cols,rows)-1))){
            //若threshold 小于 矩阵中最大的数位之和 大于 矩阵最长边数位之和的最小值(矩阵左上角)
            //最短边上的数位之和的最大值一定是(0,y)或(x,0)
            return ((threshold+1)-(Max(cols,rows)-1))*Max(cols,rows)-1;
        }
        if ((threshold>(Max(cols,rows)-1))&&(threshold<(Min(cols,rows)-1))){
            return Min(cols,rows)*Min(cols,rows)+(((threshold-Min(cols,rows)+1)+1)*(threshold-Min(cols,rows)+1)/2);
        }
        if (threshold<(Min(cols,rows)-1)){
            return (((threshold+1)+1)*(threshold+1)/2);
        }
        return 0;
    }

    //求两数最小值
    public int Min(int a,int b){
        if (a>b) return b;
        if (a<b) return a;
        else return a;
    }

    //求两数最大值
    public int Max(int a ,int b){
        if (a>b) return a;
        if (a<b) return b;
        else return a;
    }

    //求一个数的数位之和
    public int sumNum(int x){
        int n = x%10;
        x = x - n;
        int m = x/10;
        int sum = 0;
        sum = sum + n;

        while (m!=0){
            sum = sum + m%10;
            m = m/10;
        }
        return sum;
    }
}

在这里插入图片描述
在这里插入图片描述
我也找不到哪里错了,自己感觉逻辑还是对的,有没有大佬帮我纠正纠正,谢谢~

大神分析

这个方格也可以看出一个m*n的矩阵。同样在这个矩阵中,除边界上的格子之外其他格子都有四个相邻的格子。
  机器人从坐标(0,0)开始移动。当它准备进入坐标为(i,j)的格子时,通过检查坐标的数位和来判断机器人是否能够进入。如果机器人能够进入坐标为(i,j)的格子,我们接着再判断它能否进入四个相邻的格子(i,j-1)、(i-1,j),(i,j+1)和(i+1,j)。

大神代码

public class Solution {
    private int sum;
    public int movingCount(int threshold, int rows, int cols)
    {
        sum = 0;
        boolean[][] vis = new boolean[rows][cols];
        Solve(0,0,rows,cols,vis,threshold);
        return sum;
    }
    public void Solve(int x, int y, int rows, int cols, boolean[][] vis, int threshold){
        if (x<0 || y<0 || x>=rows || y>=cols || vis[x][y] || ((numSum(x)+numSum(y))>threshold)){
            return;
        }
        vis[x][y] = true;
        sum++;
        Solve(x+1, y, rows, cols, vis, threshold);
        Solve(x-1, y, rows, cols, vis, threshold);
        Solve(x, y+1, rows, cols, vis, threshold);
        Solve(x, y-1, rows, cols, vis, threshold);
    }

    public int numSum(int x){
        int res = 0;
        while (x!=0){
            res += x%10;
            x /=10;
        }
        return res;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这道题可以使用回溯法来解决,时间复杂度为O(mn),空间复杂度为O(mn)。 具体实现思路如下: 1. 定义一个二维数组来表示这个方格,并初始化为0。 2. 从起点(0, 0)开始,进回溯搜索。 3. 在搜索的过程中,对于每个可的位置,我们需要检查它的坐标坐标数位之和是否小于等于k。如果小于等于k,则继续向下搜索;否则,返回上一层继续搜索。 4. 同时,我们需要记录已经搜索过的格子,以免重复搜索。可以使用一个布尔类型的二维数组来记录。 5. 最后,搜索结束后,我们可以统计一下已经搜索到的格子数,即为机器人能够到达的格子数。 下面是一个C语言的实现代码: ``` bool check(int i, int j, int k) // 判断坐标(i, j)的数位之和是否小于等于k { int sum = 0; while(i) { sum += i % 10; i /= 10; } while(j) { sum += j % 10; j /= 10; } return sum <= k; } int movingCountCore(int threshold, int rows, int cols, int i, int j, bool* visited) { int count = 0; if(i >= 0 && i < rows && j >= 0 && j < cols && !visited[i * cols + j] && check(i, j, threshold)) { visited[i * cols + j] = true; count = 1 + movingCountCore(threshold, rows, cols, i + 1, j, visited) + movingCountCore(threshold, rows, cols, i - 1, j, visited) + movingCountCore(threshold, rows, cols, i, j + 1, visited) + movingCountCore(threshold, rows, cols, i, j - 1, visited); } return count; } int movingCount(int threshold, int rows, int cols) { if(threshold < 0 || rows <= 0 || cols <= 0) return 0; bool *visited = new bool[rows * cols]; memset(visited, 0, rows * cols); int count = movingCountCore(threshold, rows, cols, 0, 0, visited); delete[] visited; return count; } ``` 其中,movingCountCore函数是回溯搜索的核心函数,movingCount函数是对外提供的接口函数。 时间复杂度分析:每个格子最多只会被访问一次,因此时间复杂度为O(mn)。 空间复杂度分析:需要一个布尔类型的二维数组来记录已经搜索过的格子,因此空间复杂度为O(mn)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值