2-24 机器人的运动范围
题目
地上有一个 m 行和 n 列的方格,横纵坐标范围分别是 0∼m−1 和 0∼n−1。
一个机器人从坐标 (0,0) 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格。
但是不能进入行坐标和列坐标的数位之和 大于 k 的格子。
请问该机器人能够达到多少个格子?
样例1
输入:k=7, m=4, n=5
输出:20
样例2
输入:k=18, m=40, n=40
输出:1484
解释:当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。
但是,它不能进入方格(35,38),因为3+5+3+8 = 19。
注意 :
0<=m<=50
0<=n<=50
0<=k<=100
典型的宽度优先搜索问题 BFS,从 (0, 0) 点开始,每次朝上下左右四个方向扩展新的节点即可。
扩展时需要注意新的节点需要满足如下条件:
- 之前没有遍历过,这个可以用个bool数组来判断;
- 没有走出边界;
- 横纵坐标的各位数字之和小于 kk;
最后答案就是所有遍历过的合法的节点个数。
时间复杂度
每个节点最多只会入队一次,所以时间复杂度不会超过方格中的节点个数。
最坏情况下会遍历方格中的所有点,所以时间复杂度就是 O(nm)。
答案
class Solution
{
public:
int get_location_nums(pair<int, int> p)
{ // 函数,即使只有一句,必须要有 {} 不能省略
int ret = 0;
while (p.first)
{
ret += p.first % 10;
p.first /= 10;
}
while (p.second)
{
ret += p.second % 10;
p.second /= 10;
}
return ret;
}
int movingCount(int threshold, int rows, int cols)
{
int ret = 0;
if (!rows || !cols)
return 0;
// 保存每个坐标位置
// pair .first .second 是变量,直接调用,不是函数
queue<pair<int, int> > q;
// 从 (0,0) 开始移动
q.push({0, 0});
vector<vector<bool> > visited(rows, vector<bool>(cols, false));
// 立足此循环点进行遍历,四面出击
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
while (q.size())
{
// 获取第一个元素
auto temp = q.front();
q.pop();
// 大于 k 或者已经遍历过,路过
if (get_location_nums(temp) > threshold || visited[temp.first][temp.second])
continue;
ret++;
visited[temp.first][temp.second] = true;
for (int i = 0; i < 4; i++)
{
int a = temp.first + dx[i], b = temp.second + dy[i];
// 小于阈值并且未遍历过,只需要确保在范围内
if (a >= 0 && a < rows && b >= 0 && b < cols)
q.push({a, b});
}
}
return ret;
}
};
注意点:
能初始化的一定要初始化,不然有未知问题!!!