题目描述
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
解法
回溯法,使用全局变量进行计数,实现代码如下:
public class Solution {
private int count;
private boolean[][] flag;
public int movingCount(int threshold, int rows, int cols)
{
count = 0;
flag = new boolean[rows][cols];
move(threshold,rows,cols,0,0);
return count;
}
public void move(int threshold,int rows,int cols,int i,int j){
//离开递归
if(i < 0||j < 0||i >= rows||j >= cols||flag[i][j] == true){
return ;
}
int s1 = i/10;
int s2 = i - s1*10;
int s3 = j/10;
int s4 = j - s3*10;
int sum = s1 + s2 + s3 + s4;
if(threshold < sum){
return ;
}
//递加
if(flag[i][j] == false){
count++;
flag[i][j] = true;
}
//移动
move(threshold,rows,cols,i + 1,j);
move(threshold,rows,cols,i - 1,j);
move(threshold,rows,cols,i,j + 1);
move(threshold,rows,cols,i,j - 1);
}
}
改良后的回溯法,直接在递归中计数,实现代码如下:
public class Solution {
private boolean[][] flag;
public int movingCount(int threshold, int rows, int cols)
{
flag = new boolean[rows][cols];
return move(threshold,rows,cols,0,0);
}
public int move(int threshold,int rows,int cols,int i,int j){
//离开递归
if(i < 0||j < 0||i >= rows||j >= cols||flag[i][j] == true){
return 0;
}
int s1 = i/10;
int s2 = i - s1*10;
int s3 = j/10;
int s4 = j - s3*10;
int sum = s1 + s2 + s3 + s4;
if(threshold < sum){
return 0;
}
//递加
flag[i][j] = true;
//移动
return
move(threshold,rows,cols,i + 1,j)
+ move(threshold,rows,cols,i - 1,j)
+ move(threshold,rows,cols,i,j + 1)
+ move(threshold,rows,cols,i,j - 1)
+ 1;
}
}