题目描述
地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
典型回溯法的问题
回溯法是一种深度优先搜索方法
按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。
算法如下:
1、首先确定初始点,将初始点的行和列加入队列中保存
2、队列不为空,弹出队首元素
3、从队首元素往上下左右搜索,能够满足小于K,且未被搜索过,加入队列中
4、重复2、3
#pragma once
#include <queue>
namespace movingCount
{
class Solution {
struct row_col
{
int _row;
int _col;
};
public:
bool** _e;
int _threshold;
int _maxr;
int _maxc;
int _sum;
int movingCount(int threshold, int rows, int cols)
{
if (rows <= 0 && cols <= 0)
{
return 0;
}
if (threshold < 0)
{
return 0;
}
// 初始化表
_threshold = threshold;
_e = new bool* [rows];
_maxr = rows;
_maxc = cols;
for (int i = 0; i < rows; i++)
{
_e[i] = new bool[cols]();
for (int j = 0; j < cols; j++)
{
_e[i][j] = false;
}
}
std::queue<row_col> que;
que.push(row_col{ 0,0 });
_e[0][0] = true;
_sum = 1;
while (!que.empty())
{
row_col rc = que.front();
que.pop();
// 遍历上下左右
satisfied( rc._row, rc._col - 1, que);
satisfied( rc._row, rc._col + 1, que);
satisfied( rc._row - 1, rc._col, que);
satisfied( rc._row + 1, rc._col, que);
}
return _sum;
}
// 判断节点是否满足条件
bool satisfied(int row, int col, std::queue<row_col> &que)
{
if (col < 0 || row < 0 || !(col < _maxc) || !(row < _maxr))
{
return false;
}
if (_e[row][col] == true)
{
return false;
}
int sum = sum_bit(row) + sum_bit(col);
if (sum <= _threshold)
{
_e[row][col] = true;
que.push(row_col{ row, col });
_sum++;
return true;
}
return false;
}
// 判断个位数的和
int sum_bit(int row)
{
int ret = 0;
while (row > 0)
{
ret += row % 10;
row /= 10;
}
return ret;
}
};
}
test.cpp
#pragma once
#include "movingCount.h"
namespace movingCount
{
void start_test()
{
Solution s;
int r= s.movingCount(10, 1, 100);
}
}