地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
//DFS, 递归实现; 需要记录访问过的节点, 但并不是回溯, 只需要改变现场, 不需要恢复现场
class Solution {
private int res;
public int movingCount(int m, int n, int k) {
//访问过的节点不能再访问了
boolean[][] flag = new boolean[m][n];
core(flag, m, n, k, 0, 0);
return res;
}
/*
递归函数逻辑:判断当前坐标(i,j)是否合法(当前条件), 不合法则不处理, 合法则处理(i,j)周围的坐标(新条件新递归)
*/
private void core(boolean[][] flag, int m, int n, int k, int i, int j){
//坐标越界 || 该点访问过 || 数位之和大于k
if(i<0 || i>= m || j<0 || j>=n || flag[i][j]==true ||digitSum(i,j)>k)
return;
//改变现场
flag[i][j]=true;
//最终结果++
res++;
//探索周围的节点(新条件新递归)
core(flag,m,n,k,i-1,j);
core(flag,m,n,k,i+1,j);
core(flag,m,n,k,i,j-1);
core(flag,m,n,k,i,j+1);
}
private int digitSum(int a, int b){
int res = 0;
while(a!=0){
res += a%10;
a /= 10;
}
while(b!=0){
res += b%10;
b /= 10;
}
return res;
}
}
public class Solution {
int count=0;
public int movingCount(int threshold, int rows, int cols)
{
if(threshold<0)
return 0;
boolean[] flag = new boolean[rows*cols];
Core(threshold, rows, cols, flag, 0, 0);
return count;
}
public void Core(int threshold, int rows, int cols, boolean[] flag, int i, int j){
if(i<0 || i>=rows || j<0 || j>=cols)
return;
int coordinate = i * cols + j;
if(digitSum(i,j)>threshold){
return;
}
if(flag[coordinate] == true)
return;
//开始忘了改变状态, 陷入了无限递归
flag[coordinate] = true;
count++;
Core(threshold, rows, cols, flag, i-1, j);
Core(threshold, rows, cols, flag, i+1, j);
Core(threshold, rows, cols, flag, i, j-1);
Core(threshold, rows, cols, flag, i, j+1);
}
public int digitSum(int i, int j){
int sum=0;
while(i!=0){
sum += i%10;
i /= 10;
}
while(j!=0){
sum += j%10;
j /= 10;
}
return sum;
}
}
public class Solution {
public int count=0;
public int movingCount(int threshold, int rows, int cols)
{
boolean[][] flag = new boolean[rows][cols];
Core(threshold, rows, cols, 0, 0, flag);
return count;
}
public void Core(int threshold, int rows, int cols, int i, int j, boolean[][] flag){
//base case
if(i<0 || i>rows-1 || j<0 || j>cols-1)
return;
if(flag[i][j]==true)
return;
if(digitSum(i,j)>threshold)
return;
count++;
flag[i][j]=true;
Core(threshold, rows, cols, i-1, j, flag);
Core(threshold, rows, cols, i+1, j, flag);
Core(threshold, rows, cols, i, j-1, flag);
Core(threshold, rows, cols, i, j+1, flag);
}
public int digitSum(int i, int j){
int sum = 0;
while(i!=0){
sum += i%10;
i /= 10;
}
while(j!=0){
sum += j%10;
j /= 10;
}
return sum;
}
}
public class Solution {
public int movingCount(int threshold, int rows, int cols)
{
boolean[] flag = new boolean[rows*cols];
for(int i=0 ; i<rows*cols; i++)
flag[i]=false;
int result = movingCountCore(threshold, rows, cols, 0, 0, flag);
return result;
}
private int movingCountCore(int threshold, int rows, int cols, int i, int j, boolean[] flag){
// 从(i,j)开始,能否向上下左右移动? 可以同时探索多个方向
// 走过的地方就不能再走了, 注意标识一下flag
// 判断(i,j)是否越界, (i,j)能否到达, (i,j)数位和是否大于threshold
int index = i*cols+j;
if(i<0 || i>= rows || j<0 || j>=cols || flag[index]==true || sumLargerThanK(i, j, threshold))
return 0;
// 执行到这里说明(i,j)可以到达, 对应的flag置true, 表示不能再到达(i,j)
flag[index] = true;
// 计数加一, 之后继续递归探索(i,j)上下左右的点
int count = 0;
count = 1 + movingCountCore(threshold, rows, cols, i+1, j, flag) +
movingCountCore(threshold, rows, cols, i-1, j, flag) +
movingCountCore(threshold, rows, cols, i, j+1, flag) +
movingCountCore(threshold, rows, cols, i, j-1, flag);
return count;
}
private boolean sumLargerThanK(int i, int j, int threshold){
return getSum(i)+getSum(j) > threshold;
}
private int getSum(int i){
int sum=0;
while(i>0){
sum += i%10;
i /= 10;
}
return sum;
}
}