剑指Offer-机器人的运动范围
地上有一个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
示例 1:
输入:m = 3, n = 1, k = 0
输出:1
思路
与《矩阵中的路径》那道题类似,也是dfs+回溯,不过这道题有一些可以优化的点。
首先,通过分析解的情况,我们可以知道机器人只能向右或者向下走(类似一个直角三角形),排除向左和向上走的情况。
利用一个记忆矩阵visited,标识已经走过的路。不能重复地走。也是为了递归函数的出栈。
class Solution {
//记忆矩阵
boolean[][] visited;
public int movingCount(int m, int n, int k) {
//对记忆矩阵初始化
this.visited=new boolean[m][n];
return dfs(m,n,0,0,k);
}
public int dfs(int m,int n,int i,int j,int k)
{
if(i<0 || i>=m || j<0 || j>=n || getSum(i,j)>k || visited[i][j])
{
return 0;
}
//设置标记,回溯回来的时候直接返回
visited[i][j]=true;
//这里直接返回,与《矩阵中路径》那题不同,因为那题是穷举所有可能性,这题是找最大值,且不会
//遍历矩阵中所有元素,只是从(0,0)点出发深搜回溯而已。
//根据直角三角形的形状,只向右或向下走。
return 1+(dfs(m,n,i+1,j,k) + dfs(m,n,i,j+1,k));
}
//获得某个点横纵座标的位数和的函数
public int getSum(int x,int y)
{
int sum=0;
while(x>0)
{
sum+=x%10;
x=x/10;
}
while(y>0)
{
sum+=y%10;
y=y/10;
}
return sum;
}
}