题目描述:
地上有一个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
示例 2:
输入:m = 3, n = 1, k = 0
输出:1
提示:
1 <= n,m <= 100
0 <= k <= 20
代码:
方法一:
class Solution {
//广搜BFS,时间复杂度O(mn) 空间复杂度O(mn)
public int movingCount(int m, int n, int k) {
//k为0的话,机器人无法移动只走过起点
if(k == 0){
return 1;
}
//创建队列,用来存储过程中经过的可走点,所以里面放了数组,因为存储的是坐标
Queue<int[]> queue = new LinkedList<>();
//方向数组,广搜我们从矩阵左上角开始搜索,所以不需要在中间点再去搜索该点的上面或这左面的点,因为之前已经考虑过了
//所以在搜索过程中我们只需要向下或者向右
int[] dx = {0,1};
int[] dy = {1,0};
//标记数组
boolean[][] vis = new boolean[m][n];
//起点入队列并将其标记为已走
queue.offer(new int[]{0,0});
vis[0][0] = true;
int ans =1;
while(!queue.isEmpty()){
//取出队首元素并从队列中删除
int[] tmp = queue.poll();
int x = tmp[0], y = tmp[1];
for(int i = 0; i < 2; i++){
int tmpx = dx[i] + x;
int tmpy = dy[i] + y;
//越界和大于k的情况
if(tmpx<0||tmpx>=m||tmpy<0||tmpy>=n||vis[tmpx][tmpy]||getSum(tmpx)+getSum(tmpy)>k){
continue;
}
queue.offer(new int[]{tmpx,tmpy});
vis[tmpx][tmpy] = true;
ans +=1;
}
}
return ans;
}
//获得数位之和
public int getSum(int x){
int sum = 0;
while(x != 0){
sum += (x % 10);
x = x/10;
}
return sum;
}
}
方法二:
class Solution {
//dp,动态转移方程 vis[i][j] = vis[i-1][j] || vis[i][j-1]; 其中i>0,j>0
//时间复杂度O(mn) 空间复杂度O(mn)
public int movingCount(int m, int n, int k) {
//k为0的话,机器人无法移动只走过起点
if(k == 0){
return 1;
}
boolean[][] vis = new boolean[m][n];
vis[0][0] = true;
int ans = 0;
//遍历数组
for(int i = 0; i < m ; i++){
for(int j = 0;j < n;j++){
//不符合条件
if(getSum(i) + getSum(j) >k){
continue;
}
//该点,只能是由上方的点或者左方的点过来的,所以如果前一个点能到达,该点就一定能到达
if(i - 1 >= 0){
vis[i][j] |= vis[i-1][j];
}
if(j - 1 >= 0){
vis[i][j] |= vis[i][j-1];
}
ans += (vis[i][j] == true ? 1 : 0);
}
}
return ans;
}
//获得数位之和
public int getSum(int x){
int sum = 0;
while(x != 0){
sum += (x % 10);
x = x/10;
}
return sum;
}
}