题目:
地上有一个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。请问该机器人能够到达多少个格子?
示例 :
输入:m = 2, n = 3, k = 1
输出:3
来源:
解题思路:
此题考查的是图的搜索,不管深度优先还是广度优先都是可以的,另外我们可以提前计算每个格子的数位之和,搜索时当和大于k时不能进入。标记访问过的坐标,最后数一下标记坐标的数量即可。
如下图,m=n=20,当k=9时,蓝色区域是可以访问的,橙色区域虽然"和"满足条件但没路径可达,所以也不可访问。
广度优先搜索需要配合队列使用,写起来相对麻烦,而深度优先搜索可以递归调用,代码简洁,所以我采用深度优先搜索,代码如下:
int num(int n) {
int ret = 0;
while (n > 0) {
ret += n % 10;
n /= 10;
}
return ret;
}
void dfs(int data[][101], int m, int n, int x, int y, int k) {
if (data[x][y] == -1 || data[x][y] > k) {
return;
}
data[x][y] = -1; // 设置访问标记
if (x > 0) dfs(data, m, n, x-1, y, k); // 上
if (x+1 < m) dfs(data, m, n, x+1, y, k);// 下
if (y > 0) dfs(data, m, n, x, y-1, k); // 左
if (y+1 < n) dfs(data, m, n, x, y+1, k);// 右
}
int movingCount(int m, int n, int k){
int data[101][101] = {0};
// 提前计算数位之和
for (int i = 1; i < m; i++) {
int t = num(i);
for (int j = 0; j < n; j++) {
data[i][j] = t;
}
}
for (int j = 1; j < n; j++) {
int t = num(j);
for (int i = 0; i < m; i++) {
data[i][j] += t;
}
}
// 深度优先搜索
dfs(data, m, n, 0, 0, k);
// 数一下
int count = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (data[i][j] < 0) count++;
}
}
return count;
}