剑指 Offer 13. 机器人的运动范围

题目描述

地上有一个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:

1
2
输入:m = 2, n = 3, k = 1
输出:3

示例 2:

1
2
输入:m = 3, n = 1, k = 0
输出:1

提示:

  • $1 <= n,m <= 100$
  • $0 <= k <= 20$

算法

(BFS)) $O(nm)$

$BFS$ 搜索所有可以到达的格子,初始状态将起点加入队列中,如果队列不为空,则弹出队头作为新的起点,如果当前点可以走,则枚举四个方向扩展下一层,将所有没有越界的点加入队列中,直到队列为空所有点就都被遍历完了。

哪些点可以走呢?

  1. 没有走过的点
  2. 当前点横纵坐标每位之和小于等于 $k$

时间复杂度

最坏情况下每个点都会被遍历一次,所以时间复杂度为 $O(nm)$。

空间复杂度

$O(nm)$

C++ 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Solution {
public:
int get(int x) {
int res = 0;
while (x) {
res += x % 10;
x /= 10;
}
return res;
}

int movingCount(int m, int n, int k) {
vector<vector<bool>> st(m, vector<bool>(n, false));
int res = 0;

queue<pair<int, int>> q;
q.push({0, 0});

int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while (q.size()) {
auto t = q.front();
q.pop();

int x = t.first, y = t.second;
if (st[x][y] || get(x) + get(y) > k) continue;

res ++ ;
st[x][y] = true;

for (int i = 0; i < 4; i ++ ) {
int a = x + dx[i], b = y + dy[i];
if (a < 0 || a >= m || b < 0 || b >= n) continue;
q.push({a, b});
}
}

return res;
}
};
Author: tonngw
Link: https://tonngw.com/2022/07/09/剑指 Offer/剑指 Offer 13. 机器人的运动范围/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.