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

    可以用深度优先搜索:每走一步都要判断这一步能不能走,显然最外围一圈不能走,然后根据题意,格子行列各个位加起来不能大于阈值threshold。然后走到下一个格子,走法是一样的,所以可以递归实现。注意:被访问过的格子需要用记录一下。不然会一个格子会被访问多次。
    image.png
    DFS解法

    1. public class Solution {
    2. public int movingCount(int threshold, int rows, int cols){
    3. if (rows <= 0 || cols <= 0 || threshold < 0)
    4. return 0;
    5. boolean[][] isVisited = new boolean[rows][cols];
    6. return movingCountIntervals(threshold, rows, cols, 0, 0, isVisited);
    7. }
    8. public int movingCountIntervals(int threshold, int rows, int cols, int row, int col, boolean[][] isVisited){
    9. if (row<0 || row>=rows || col<0 || col>=cols || checkSum(col)+checkSum(row)>threshold || isVisited[row][col]){
    10. return 0;
    11. }
    12. isVisited[row][col] = true;
    13. //其实当前节点的左节点和上节点已经被访问过了所以下面的movingCountIntervals(threshold, rows, cols, row-1, col, isVisited)和
    14. //movingCountIntervals(threshold, rows, cols, row, col-1, isVisited)是多余的
    15. return 1 + movingCountIntervals(threshold, rows, cols, row+1, col, isVisited)
    16. + movingCountIntervals(threshold, rows, cols, row-1, col, isVisited)
    17. + movingCountIntervals(threshold, rows, cols, row, col+1, isVisited)
    18. + movingCountIntervals(threshold, rows, cols, row, col-1, isVisited);
    19. }
    20. public int checkSum(int num){
    21. int sum=0;
    22. while(num>0){
    23. sum += num%10;
    24. num /= 10;
    25. }
    26. return sum;
    27. }
    28. }

    BFS解法

    1. import java.util.LinkedList;
    2. import java.util.Queue;
    3. public class BFS {
    4. public static void main(String[] args) {
    5. System.out.println(BFS.movingCount(3,10,10));
    6. }
    7. public static int checkSum(int num){
    8. int sum=0;
    9. while(num>0){
    10. sum += num%10;
    11. num /= 10;
    12. }
    13. return sum;
    14. }
    15. public static int movingCount(int threshold, int rows, int cols){
    16. if(rows<=0 || cols<=0 || threshold<0)
    17. return 0;
    18. int result=0;
    19. //BFS
    20. Queue<Integer> queue = new LinkedList<>();
    21. boolean[][] isVisited = new boolean[rows][cols];
    22. queue.offer(0);
    23. while(!queue.isEmpty()){
    24. int row = queue.peek()/cols;
    25. int col = queue.peek()%cols;
    26. if(row<rows && col<cols && checkSum(row)+checkSum(col)<=threshold && !isVisited[row][col]){
    27. result++;
    28. isVisited[row][col] = true;
    29. queue.offer((row+1)*cols+col);
    30. queue.offer(row*cols+col+1);
    31. }
    32. queue.poll();
    33. }
    34. return result;
    35. }
    36. }

    DFS+回溯
    image.png
    由于每一个位置都有可能是搜索的起点,对于每一个搜索的位置来说,用DFS递归查找需要的路径。
    先定义递归DFS函数:
    find(){
    第一步,递归出口
    第二步,检查元素是否被访问过``<br />
    第三步,都没有返回,继续递归
    find()
    回溯
    }

    1. public boolean find(char[][] array, int rows, int cols, int row, int col, char[] str, int str_pos, boolean isVisited[][]){
    2. //递归出口条件
    3. //当 row<0 || row>=rows || col<0 || col>=cols || isVisited[row][col] || array[row][col] != str[str_pos] 满足任意一条返回 false,说明此路不通;
    4. //当 str_pos == str.length 返回 true, 表示数组中有这条路径,递归结束;
    5. if(row<0 || row>=rows || col<0 || col>=cols || isVisited[row][col] || array[row][col] != str[str_pos])
    6. return false;
    7. if(str_pos == str.length)
    8. return true;
    9. //标记这个位置已经被访问过了
    10. isVisited[row][col] = true;
    11. //程序能走到这里说明当前位置没有越界,并且array[row][col] == str[str_pos],这样就可以继续往下搜索了
    12. boolean result = find(array, rows, cols, row-1, col, str, str_pos+1, isVisited)
    13. || find(array, rows, cols, row, col+1, str, str_pos+1, isVisited)
    14. || find(array, rows, cols, row+1, col, str, str_pos+1, isVisited)
    15. || find(array, rows, cols, row, col-1, str, str_pos+1, isVisited);
    16. //非常重要的一步:回溯. 如果不回溯的话,假设某一次递归时,访问到当前位置设为(x,y), 但是此路不通,
    17. //也就是说这条路径搜索不到我们想要的字符串。这时,所有的递归都不能访问该位置,程序就是错的
    18. isVisited[row][col] = false;
    19. return result;
    20. }
    21. //输入的是一维字符数组,转成二维数组,容易理解
    22. public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
    23. visit = new int[rows][cols];
    24. char[][] array = new char[rows][cols];
    25. for (int i = 0; i < rows ; i++) {
    26. for(int j = 0; j < cols; j++) {
    27. array[i][j] = matrix[i*cols + j];
    28. }
    29. }
    30. for (int i = 0; i < rows ; i++) {
    31. for(int j = 0; j < cols; j++) {
    32. if(find(array,rows,cols,str,i,j,0)){
    33. return true;
    34. }
    35. }
    36. }
    37. return false;
    38. }