[菜鸟训练]剑指 Offer 13. 机器人的运动范围

这篇博客讨论了如何使用广度优先搜索(BFS)和动态规划(DP)两种方法来解决机器人在m行n列的网格中移动的问题。当行和列坐标的数位之和不超过k时,机器人可以到达某些格子。博客提供了两个Java实现的解决方案,分别用BFS和DP来计算机器人能到达的格子总数,并给出了多个示例测试用例。
摘要由CSDN通过智能技术生成

题目描述:

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

代码:

方法一:

class Solution {
	//广搜BFS,时间复杂度O(mn) 空间复杂度O(mn)
    public int movingCount(int m, int n, int k) {
        //k为0的话,机器人无法移动只走过起点
        if(k == 0){
            return 1;
        }
        //创建队列,用来存储过程中经过的可走点,所以里面放了数组,因为存储的是坐标
        Queue<int[]> queue = new LinkedList<>();
        //方向数组,广搜我们从矩阵左上角开始搜索,所以不需要在中间点再去搜索该点的上面或这左面的点,因为之前已经考虑过了
        //所以在搜索过程中我们只需要向下或者向右
        int[] dx = {0,1};
        int[] dy = {1,0};
        //标记数组
        boolean[][] vis = new boolean[m][n];
        //起点入队列并将其标记为已走
        queue.offer(new int[]{0,0});
        vis[0][0] = true;
        int ans =1;
        while(!queue.isEmpty()){
            //取出队首元素并从队列中删除
            int[] tmp = queue.poll();
            int x = tmp[0], y = tmp[1];
            for(int i = 0; i < 2; i++){
                int tmpx = dx[i] + x;
                int tmpy = dy[i] + y;
                //越界和大于k的情况
                if(tmpx<0||tmpx>=m||tmpy<0||tmpy>=n||vis[tmpx][tmpy]||getSum(tmpx)+getSum(tmpy)>k){
                    continue;
                }
                queue.offer(new int[]{tmpx,tmpy});
                vis[tmpx][tmpy] = true;
                ans +=1;
            }
        }
        return ans;
    }
    //获得数位之和
    public int getSum(int x){
        int sum = 0;
        while(x != 0){
            sum += (x % 10);
            x = x/10;
        }
        return sum;
    }
}

方法二:

class Solution {
    //dp,动态转移方程 vis[i][j] = vis[i-1][j] || vis[i][j-1]; 其中i>0,j>0
    //时间复杂度O(mn) 空间复杂度O(mn)
    public int movingCount(int m, int n, int k) {
        //k为0的话,机器人无法移动只走过起点
        if(k == 0){
            return 1;
        }
        boolean[][] vis = new boolean[m][n];
        vis[0][0] = true;
        int ans = 0;
        //遍历数组
        for(int i = 0; i < m ; i++){
            for(int j = 0;j < n;j++){
                //不符合条件
                if(getSum(i) + getSum(j) >k){
                    continue;
                }
                //该点,只能是由上方的点或者左方的点过来的,所以如果前一个点能到达,该点就一定能到达
                if(i - 1 >= 0){
                    vis[i][j] |= vis[i-1][j];
                }
                if(j - 1 >= 0){
                    vis[i][j] |= vis[i][j-1];
                }
                ans += (vis[i][j] == true ? 1 : 0);
            }
        }
        
        return ans;
    }
    //获得数位之和
    public int getSum(int x){
        int sum = 0;
        while(x != 0){
            sum += (x % 10);
            x = x/10;
        }
        return sum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值