2.题目描述:
地上有一个 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 | |
| • |
| |
3. 算法思路:
这是一道非常典型的「搜索」类问题。
我们可以通过「深搜」或者「宽搜」,从 [0, 0] 点出发,按照题目的「规则」一直往 [m - 1, n - 1] 位置走。
同时,设置一个全局变量。每次走到一个合法位置,就将全局变量加一。当我们把所有能走到的路都走完之后,全局变量里面存的就是最终答案。
4. 解法(dfs):
算法流程:
| • | 递归函数设计: |
a. 参数:当前所在的位置 [i, j] ,行走的边界 [m, n] ,坐标数位之和的边界 k ;b. 递归出口:
| i. | [i, j] 的坐标不合法,也就是已经超出能走的范围; |
| ii. | [i, j] 位置已经走过了(因此我们需要创建一个全局变量 bool st[101][101] , |
来标记当前位置是否走过);
| iii. | [i, j] 坐标的数位之和大于 k ; |
上述情况的任何一种都是递归出口。
c. 函数体内部:
| i. | 如果这个坐标是合法的,就将全局变量 ret++ ; |
ii. 然后标记一下 [i, j] 位置已经遍历过;
iii. 然后去 [i, j] 位置的上下左右四个方向去看看。
| • | 辅助函数: |
a. 检测坐标 [i, j] 是否合法;
b. 计算出 i,j 的数位之和,然后与 k 作比较即可。
| • | 主函数: |
a. 调用递归函数,从 [0 ,0] 点出发。
| • | 辅助的全局变量: |
a. 二维数组 bool st[101][101] :标记 [i, j] 位置是否已经遍历过;
b. 变量 ret :记录一共到达多少个合法的位置。
c. 上下左右的四个坐标变换。
Java算法代码:
class Solution {
int m,n,k;
boolean[][] vis;
int [] dx = {1,-1,0,0};
int [] dy = {0,0,1,-1};
int ret;
public int wardrobeFinishing(int _m, int _n, int _k) {
m = _m; n = _n; k = _k;
vis = new boolean[m][n];
dfs(0,0);
return ret;
}
public void dfs(int i, int j){
ret++;
vis[i][j] = true;
for(int k = 0;k<4;k++){
int x = i + dx[k], y = j + dy[k];
if(x>= 0 && x < m && y>= 0 && y < n && !vis[x][y] && check(x,y))
dfs(x,y);
}
}
public boolean check(int i, int j){
int tmp = 0;
while( i != 0){
tmp += i %10;
i /= 10;
}
while(j != 0){
tmp += j%10;
j /= 10;
}
return tmp <= k;
}
}
运行结果:

递归展开:
这道题的重点是理解题干(知道check这个方法怎么写出来的就行)

逻辑展开:
直接根据 下, 上,右,左的顺序来人工手动遍历。
---------------------------------------------------------------------------------------------------------------------------------
记住,相信你的递归函数,它可以做到!
记住,不理解时候,去尝试手动展开!
记住,逻辑展开(你不可能对所有的题目都进行手动展开)!
1125

被折叠的 条评论
为什么被折叠?



