【面试题】——机器人的运动范围,用回溯算法解决

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

实例解析

这道题就像走迷宫一样,最终走完纪录我们行走了多少步

那么在计算机中如何进行走迷宫?其实用的就是回溯算法

  • 当我们走一条路走不通的时候,就退回一步,走下个方向
  • 走下个方向后,当这条路也走不通的时候,就再退回一步
  • 当退回之后,发现这个位置没有其它方向可以走了,就再回退
  • 依次回退到起始点为止

以我们这道题为例

  • 矩阵上的数字为题中所述(行坐标和列坐标的数位之和),例如(3,2)为3+2 = 5;(12,25)为1 + 2 + 2 + 5 = 10
  • 圆圈代表当前搜索到的位置
  • 黄色代表走过的位置
  • 假设 m = 4, n = 4, k = 2
  • 按左上右下的方向查找

如上图所示

首先,当前位置数字为0

  • 第一步:当前为0,左面越界、上面越界、右面为1 <= k,所以向右走一格
  • 第二步:当前为1,左面走过、上面越界、右面为2 <= k,所以向右走一格
  • 第三步:当前为2,左面走过、上面越界、右面为3 > k、下面为3 > k,没有地方可以走,所以回退一格
  • 第四步:当前为1,这个位置已经判断过左、上、右,所以只能判断向下,下面为2 >= k,所以向下走一格
  • 第五步:当前为2,左面为1 <= k,所以向左走一格
  • 第六步:当前为1,左面越界、上面走过、右面走过,下面为为2 <= k,所以向下走一格
  • 此时已经没有位置可以走了,所以回溯到上一个位置,然后上一个位置也没有位置可以走了,所以再继续回溯,因为图中已经没有可以走的格子了,所以一直回溯到0的位置结束(第七步之后的回溯没画在图中)

所以这个机器人一共走了6个格子

Java代码

package LeetCode;

/**
 * 中等题——机器人的运动范围
 */
public class Solution2 {
    private int[][] matrix; // 全0数组,为了得到数组下标
    private int[][] moveStep; // 走过的位置置1
    private int count = 0;
    public int movingCount(int m, int n, int k) {
        matrix = new int[m][n];
        moveStep = new int[m][n];
        // 为数组赋值
        for (int i = 0 ; i < m ; i++) {
            for (int j = 0 ; j < n ; j++) {
                matrix[i][j] = getIndexSum(i, j);
            }
        }
        moveStep[0][0] = 1;
        // 移动
        move(0, 0, k);
        return count;
    }
    private void move(int x, int y, int k) {
        moveStep[x][y] = 1;
        count++;
        // 向左
        if (canMove(x , y - 1, k)) {
            move(x, y - 1, k);
        }
        // 向上
        if (canMove(x - 1, y, k)) {
            move(x - 1, y, k);
        }
        // 向右
        if (canMove(x, y + 1, k)) {
            move(x, y + 1, k);
        }
        // 向下
        if (canMove(x + 1, y, k)) {
            move(x + 1, y, k);
        }
    }
    // 判断能否走这个位置
    private boolean canMove(int x, int y, int k) {
        if (x >= 0 && x < matrix.length && y >= 0 && y < matrix[x].length) {
            if (matrix[x][y] <= k && moveStep[x][y] == 0) {
                return true;
            }
        }
        return false;
    }
    // 获取坐标位数之和,例如[12, 25] = 1 + 2 + 2 + 5 = 10
    private int getIndexSum(int x, int y) {
        int sum = 0;
        String xs = String.valueOf(x);
        String ys = String.valueOf(y);

        for (int i = 0 ; i < xs.length() ;i++) {
            sum += Integer.parseInt(String.valueOf(xs.charAt(i)));
        }
        for (int i = 0 ; i < ys.length() ;i++) {
            sum += Integer.parseInt(String.valueOf(ys.charAt(i)));
        }
        return sum;
    }

    public static void main(String[] args) {
        Solution2 solution2 = new Solution2();
        System.out.println(solution2.movingCount(4, 4, 2));
    }
}

这是LeetCode上的一道题,我用的是回溯算法,其实还有其它解法,或者看看官方解答

大家可以尝试去刷一下这道题:机器人的运动范围

发布了34 篇原创文章 · 获赞 20 · 访问量 6974

猜你喜欢

转载自blog.csdn.net/weixin_42193813/article/details/105394231