• 一、题目
  • 二、解题思路
  • 三、解题代码

    一、题目

    地上有个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,它每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数位之和大于k的格子。

    举例分析

    例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7=18.但它不能进入方格(35,38),因为3+5+3+8=19.请问该机器人能够达到多少格子?

    二、解题思路

    这个方格也可以看出一个m*n的矩阵。同样在这个矩阵中,除边界上的格子之外其他格子都有四个相邻的格子。

    机器人从坐标(0,0)开始移动。当它准备进入坐标为(i,j)的格子时,通过检查坐标的数位和来判断机器人是否能够进入。如果机器人能够进入坐标为(i,j)的格子,我们接着再判断它能否进入四个相邻的格子(i,j-1)、(i-1,j),(i,j+1)和(i+1,j)。

    三、解题代码

    1. public class Test {
    2. /**
    3. * 题目:地上有个m行n列的方格。一个机器人从坐标(0,0)的格子开始移动,
    4. * 它每一次可以向左、右、上、下移动一格,但不能进入行坐标和列坐标的数
    5. * 位之和大于k的格子。例如,当k为18时,机器人能够进入方格(35,37),
    6. * 因为3+5+3+7=18.但它不能进入方格(35,38),因为3+5+3+8=19.
    7. * 请问该机器人能够达到多少格子?
    8. *
    9. * @param threshold 约束值
    10. * @param rows 方格的行数
    11. * @param cols 方格的列数
    12. * @return 最多可走的方格
    13. */
    14. public static int movingCount(int threshold, int rows, int cols) {
    15. // 参数校验
    16. if (threshold < 0 || rows < 1 || cols < 1) {
    17. return 0;
    18. }
    19. // 变量初始化
    20. boolean[] visited = new boolean[rows * cols];
    21. for (int i = 0; i < visited.length; i++) {
    22. visited[i] = false;
    23. }
    24. return movingCountCore(threshold, rows, cols, 0, 0, visited);
    25. }
    26. /**
    27. * 递归回溯方法
    28. *
    29. * @param threshold 约束值
    30. * @param rows 方格的行数
    31. * @param cols 方格的列数
    32. * @param row 当前处理的行号
    33. * @param col 当前处理的列号
    34. * @param visited 访问标记数组
    35. * @return 最多可走的方格
    36. */
    37. private static int movingCountCore(int threshold, int rows, int cols,
    38. int row, int col, boolean[] visited) {
    39. int count = 0;
    40. if (check(threshold, rows, cols, row, col, visited)) {
    41. visited[row * cols + col] = true;
    42. count = 1
    43. + movingCountCore(threshold, rows, cols, row - 1, col, visited)
    44. + movingCountCore(threshold, rows, cols, row, col - 1, visited)
    45. + movingCountCore(threshold, rows, cols, row + 1, col, visited)
    46. + movingCountCore(threshold, rows, cols, row, col + 1, visited);
    47. }
    48. return count;
    49. }
    50. /**
    51. * 断机器人能否进入坐标为(row, col)的方格
    52. *
    53. * @param threshold 约束值
    54. * @param rows 方格的行数
    55. * @param cols 方格的列数
    56. * @param row 当前处理的行号
    57. * @param col 当前处理的列号
    58. * @param visited 访问标记数组
    59. * @return 是否可以进入,true是,false否
    60. */
    61. private static boolean check(int threshold, int rows, int cols,
    62. int row, int col, boolean[] visited) {
    63. return col >= 0 && col < cols
    64. && row >= 0 && row < rows
    65. && !visited[row * cols + col]
    66. && (getDigitSum(col) + getDigitSum(row) <= threshold);
    67. }
    68. /**
    69. * 一个数字的数位之和
    70. *
    71. * @param number 数字
    72. * @return 数字的数位之和
    73. */
    74. private static int getDigitSum(int number) {
    75. int result = 0;
    76. while (number > 0) {
    77. result += (number % 10);
    78. number /= 10;
    79. }
    80. return result;
    81. }
    82. }