题目来源:
牛客网
编程链接
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
这道题考察的是BFS,即广度优先算法。
也叫回溯法。
先到1个格子,将这个格子放进队列,取出这个格子并判断这个格子符不符合要求,之后再遍历这个格子的四周四个格子,并存入队列。,当队列为空的时候则判断完毕。
1、注意判断的条件是坐标的位数之和不大于某数。位数之和本身就是一个小题。
int Sum(int x)
{
int cnt =0
for(;x; cnt +=x%10,x/=10);
return ret;
}
2、注意移动格子每次只能一个方向。
dirx = [0,0,1,-1]
diry = [1,-1,0,0]
for(int i= 0;i<4;i++)
{
x = x + dirx[i];
y = y + diry[i];
}
这样通过一个for就找到了四个周边的格子。
3、矩阵的行列可以用数学技巧表示。
x*cols + y = number ;
//number表示数组中顺序拍下来的index,arrays[x,y]即是数组的位置。
//cols是数组的列数。
x = number/ cols; y = number % cols;
4、要记录此格子是否被判过。
vector<bool> uesd(rows*cols,false);//初始化一个记录的bool数组
于是代码如下:
class Solution {
public:
int getSum(int x) {
int ret = 0;
for (; x; ret += x % 10, x /= 10);
return ret;
}
int movingCount(int threshold, int rows, int cols)
{
const int dirx[] = {0, 0, 1, -1};
const int diry[] = {1, -1, 0, 0};
queue<int> que;
vector<bool> used(rows * cols, false);
que.push(0 * cols + 0);
used[0 * cols + 0] = true;
int ret = 0;
while (!que.empty()) {
auto now = que.front();
que.pop();
if (getSum(now / cols) + getSum(now % cols) <= threshold)
ret++;
else
continue;
for (int i = 0; i < 4; i++) {
int tx = now / cols + dirx[i],
ty = now % cols + diry[i];
if (tx >= 0 && tx < rows && ty >= 0 && ty < cols &&
!used[tx * cols + ty]) {
used[tx * cols + ty] = true;
que.push(tx * cols + ty);
}
}
}
return ret;
}
};