1.题目详解 LCR 130.衣橱整理
2.题目描述
家居整理师将待整理衣橱划分为 m x n
的二维矩阵 grid
,其中 grid[i][j]
代表一个需要整理的格子。整理师自 grid[0][0]
开始 逐行逐列 地整理每个格子。
整理规则为:在整理过程中,可以选择 向右移动一格 或 向下移动一格,但不能移动到衣柜之外。同时,不需要整理 digit(i) + digit(j) > cnt
的格子,其中 digit(x)
表示数字 x
的各数位之和。
请返回整理师 总共需要整理多少个格子。
示例 1:
输入: m = 4, n = 7, cnt = 5
输出: 18
提示:
1 <= n, m <= 100
0 <= cnt <= 20
3.算法思路
这是一道很典型的深度搜索类问题。 看思路:
- 首先是要从(0,0)坐标出发,需要满足在矩阵内,即不越界。以及坐标数位之和要 <= cnt
- 若满足上面条件,则次数+1
- 按照深度搜索DFS的顺序进行遍历搜索查找(下、右)
- 与此同时,要考虑已访问过的(i,j)不能重复访问,即要做剪枝处理。可以用一个二维数组arr[i][j],存放已访问过的格子。若已访问过,arr[i][j]设为true。每次访问前需要先判断格子是否已访问过,避免重复访问。
终止条件:
(1)数组越界|| 行坐标与列坐标数位之和 > cnt || 当前[i][j]已访问过
(2)其他条件 +1
4. 代码实现
class Solution {
/**
*
* 终止条件
* (1)数组越界||超过不需要整理的数值|| 行坐标与列坐标数位之和 > cnt || 当前[i][j]已访问过
* (2)其他条件 +1
*
*
* 实现流程:
* (1)从(0,0)出发,需要满足在矩阵内与数位之和<=cnt。若超出边界或者行坐标与列坐标数位之和 > cnt, +0
* (2)判断格子是否已整理过,做剪枝处理
* 将每个坐标对应的值存储到一个boolean二维数组中,如果没有整理过,就置为true且+1;每次整理前先判断该格是否已整理
* (3)按照DFS的顺序进行搜索查找(下、右)
*
*/
int count = 0;
public int wardrobeFinishing(int m, int n, int cnt) {
//用来做标记的数组
boolean[][] arr = new boolean[m][n];
//从(0,0)坐标开始
dfs(0,0,m,n,cnt,arr);
return count;
}
public void dfs(int i, int j, int m, int n, int cnt, boolean[][] arr){
int sum = getSum(i) + getSum(j);
//1、数组越界;i与j数位之和 > cnt;各自已经被整理过,不需要整理,直接跳过
if(i >= m || j >= n || i < 0 || j < 0 || sum > cnt || arr[i][j]) return;
//2、格子没有整理过,标记为整理true,次数+1。防止重复整理
arr[i][j] = true;
count++;
//3、DFS深度向下遍历
dfs(i+1,j,m,n,cnt,arr);
dfs(i,j+1,m,n,cnt,arr);
}
/**
* 获取各数位之和
**/
private int getSum(int x){
int res = 0;
while(x != 0){
res += x % 10;
x = x / 10;
}
return res;
}
}