【剑指Offer】66、机器人的运动范围

  题目描述:

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

  解题思路:

  本题和上一题:65、矩阵中的路径 很类似,同样是一道典型的回溯搜索的题目,代码模板基本类似。同样的,题目中的方格也可以看成一个m*n的矩阵。

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

  详见如下代码实现。

  编程实现(Java):

public class Solution {
    public int movingCount(int threshold, int rows, int cols){
        if(rows<0||cols<0||threshold<0)
            return 0;
        boolean[][] flags=new boolean[rows][cols]; //标记是否访问过
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++)
                flags[i][j]=false;
        }
        return movingCount(threshold,rows,cols,0,0,flags);   
    }
    //从(i,j)出发可以到达的格子数目
    public int movingCount(int threshold,int rows,int cols,int i,int j,boolean[][] flags){
        int count=0;
        if(check(i,j,rows,cols,flags,threshold)){ //(i,j)可达
            flags[i][j]=true;
            count=1+movingCount(threshold,rows,cols,i+1,j,flags)+  
                movingCount(threshold,rows,cols,i-1,j,flags)+
                movingCount(threshold,rows,cols,i,j+1,flags)+ 
                movingCount(threshold,rows,cols,i,j-1,flags);     
        }
        return count;
    }
    //判断能否进入(row,col)的方格
    public boolean check(int row,int col,int rows,int cols,boolean[][] flags,int threshold){
        if(row<0 || row>=rows || col<0 || col>=cols) //超出范围
            return false;
        //超过范围,或者已经访问过
        if(getDigitSum(row)+getDigitSum(col)>threshold || flags[row][col]==true) 
            return false;
        return true;
    }
    //求一个数各位之和
    public int getDigitSum(int num){
        int sum=0;
        while(num!=0){
            sum+=(num%10);
            num/=10;
        }
        return sum;
    }
}
posted @ 2019-05-23 11:15  gzshan  阅读(993)  评论(0编辑  收藏  举报