今日心情:就是感觉自己啥也不会 😭😭
题目描述:
地上有一个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。请问该机器人能够到达多少个格子?
解题代码:(来自leetcode题解)
class Solution {
int m,n,k;
boolean[][] visited;
public int movingCount(int m, int n, int k) {
this.m = m;
this.n = n;
this.k = k;
this.visited = new boolean[m][n];
int count = dfs(0,0,0,0);
return count;
}
public int dfs(int i, int j, int s_i, int s_j){
//不可达点判断(返回0)
//1. 越界
//2. 超过k
//3. 已经被访问过
if(i >= m || j >= n || s_i + s_j > k || visited[i][j]){
return 0;
}
// 当前节点以及被访问,更新visited表
visited[i][j] = true;
// 递归
//求坐标的位数和(注意是下一个的)例如:[19,20] [21,22]
int ns_i = (i+1)%10 != 0 ? s_i+1:s_i-8;
int ns_j = (j+1)%10 != 0 ? s_j+1:s_j-8;
int res = 1 + dfs(i+1,j,ns_i,s_j) + dfs(i,j+1,s_i,ns_j);
return res;
}
}
解题思路:(参考的 leetcode 题解+自己的理解和思考)
(1)由于k的限制条件,所以需要判断m,n构成的位置是否具有可达性且满足条件。
(2)需要计算位置的数位和,然后再判断是否小于 k 值。
(3)通过递归回溯搜索所有满足条件的可达点。
(4)所有到达访问过的点需要进行记录标记,避免重复访问,造成重复计数。
代码解析:
(1)定义全局变量
int m,n,k; boolean[][] visited;
(2)通过movingCount(int m, int n, int k) 函数传进来的参数,赋值给全局变量,个人认为是因为可以减少dfs 递归函数的参数数量,直接使用全局变量进行操作。
(3)实现 dfs(int i, int j, int s_i, int s_j) 函数 递归回溯函数
不可达点判断(返回0):1. 越界 2. 超过k 3. 已经被访问过
if(i >= m || j >= n || s_i + s_j > k || visited[i][j]){return 0;}
否则,标记当前点已经访问搜索过,更新visited表:visited[i][j] = true;
如果没有返回0则说明当前点满足条件,此时搜寻找下一个点(向下或者向右搜寻)。
求坐标的位数和(注意是下一个的)例如:自己可以找例子实施这个求和公式
比如说:点 [19,20] , [21,22]
int ns_i = (i+1)%10 != 0 ? s_i+1:s_i-8;
int ns_j = (j+1)%10 != 0 ? s_j+1:s_j-8;
然后加1(此时访问点满足条件进行计数) 递归 向下 或者 向右进行搜索
int res = 1 + dfs(i+1,j,ns_i,s_j) + dfs(i,j+1,s_i,ns_j);
然后返回 res 计数值。
(4)在movingCount(int m, int n, int k) 函数中调用,因为 int m,n,k; boolean[][] visited; 为全局变量所以直接从 [0, 0] 开始,此时位数和分别为 0, 0
调用 dfs(0,0,0,0) 进行回溯搜索,返回所有可达切满足k条件的点。