剑指 Offer 13. 机器人的运动范围
方法一:深度优先遍历 DFS
深度优先搜索: 可以理解为暴力法模拟机器人在矩阵中的所有路径。DFS 通过递归,先朝一个方向搜到底,再回溯至上个节点,沿另一个方向搜索,以此类推。
剪枝: 在搜索中,遇到数位和超出目标值、此元素已访问,则应立即返回,称之为 可行性剪枝 。
int is_illegal(int row, int col, int k)
{
int sum = 0;
while (row > 0)
{
sum += row % 10;
row /= 10;
}
while (col > 0)
{
sum += col % 10;
col /= 10;
}
return sum <= k;
}
void dfs(int m, int n, int k, int row, int col, int& sum, vector<vector<int>>& bitMap)
{
//深度优先
if (row < 0 || row >= m || col < 0 || col >= n || !is_illegal(row, col, k) || bitMap[row][col] == 1)
return;
bitMap[row][col] = 1;
sum++;
dfs(m, n, k, row, col + 1, sum, bitMap); //先一直向右搜索
dfs(m, n, k, row + 1, col, sum, bitMap); //回到上一个节点一直向下搜索
}
int movingCount(int m, int n, int k) {
vector<vector<int>> bitMap(m, vector<int>(n, 0));
int sum = 0;
dfs(m, n, k, 0, 0, sum, bitMap);
return sum;
}
方法二:广度优先遍历 BFS
BFS/DFS : 两者目标都是遍历整个矩阵,不同点在于搜索顺序不同。DFS 是朝一个方向走到底,再回退,以此类推;BFS 则是按照“平推”的方式向前搜索。
BFS 实现: 通常利用队列实现广度优先遍历。
void bfs(int m, int n, int k)
{
int sum = 0;
vector<vector<int>> bitMap(m, vector<int>(n, 0));
std::queue<std::pair<int, int>> que;
que.push(std::make_pair(0, 0));
while (!que.empty())
{
auto& node = que.front();
if (!is_illegal(node.first, node.second, k) || bitMap[node.first][node.second] == 1)
{
//会有重复添加的值,这里要剪枝
que.pop();
continue;
}
sum++;
bitMap[node.first][node.second] = 1;
if (node.first < m && node.second + 1 < n && bitMap[node.first][node.second + 1] == 0 && is_illegal(node.first, node.second + 1, k))
que.push(std::make_pair(node.first, node.second + 1));
if (node.first + 1 < m && node.second < n && bitMap[node.first + 1][node.second] == 0 && is_illegal(node.first + 1, node.second, k))
que.push(std::make_pair(node.first + 1, node.second));
que.pop();
}
}