牛客25438题解析:机器人移动可达点数量的BFS算法优化
一、题目解读
牛客25438题要求计算在一个m行n列的网格中,从原点(0,0)出发,每次只能向上、下、左、右移动一步,且移动后的坐标各位数字之和不超过k的情况下,可达点的总数。题目考察对BFS(广度优先搜索)算法的应用,以及数字各位和的计算与边界条件的判断。
二、解题思路
采用BFS算法,通过队列存储待遍历的节点,并配合方向数组实现四方向移动。关键在于设计两个核心函数:
1. digitSum函数:通过循环取余和整除逐位拆解数字,计算各位之和。
2. isValid函数:综合判断坐标合法性(越界、数字和超限、是否已访问)。
主逻辑通过BFS从原点开始,遍历所有可达点并标记,最终统计总数量。
三、解题步骤
1. 预处理与初始化:输入m、n、k,创建visited矩阵标记访问状态,队列初始化原点。
2. BFS循环:
○ 取出队首节点,遍历四个方向偏移。
○ 调用isValid判断新坐标合法性,若合法则标记visited并入队,同时计数+1。
3. 终止条件:队列为空时结束,返回总计数。
四、代码和注释
#include <iostream> #include <queue> #include <vector> using namespace std; // 计算数字各位之和 int digitSum(int num) { int sum = 0; while (num > 0) { sum += num % 10; // 取余得末尾数字 num /= 10; // 去除末尾数字 } return sum; } // 检查坐标是否合法 bool isValid(int x, int y, int m, int n, int k, vector<vector<bool>>& visited) { return x >= 0 && x < m && y >= 0 && y < n && (digitSum(x) + digitSum(y)) <= k && !visited[x][y]; } int movingCount(int m, int n, int k) { if (m <= 0 || n <= 0 || k < 0) return 0; // 边界条件判断 vector<vector<bool>> visited(m, vector<bool>(n, false)); // 初始化访问矩阵 queue<pair<int, int>> q; // 存储待遍历坐标 int count = 0; // 可达点计数 // 初始位置(0,0) q.push({0, 0}); visited[0][0] = true; count++; // 四个移动方向 int dx[4] = {0, 1, 0, -1}; int dy[4] = {1, 0, -1, 0}; while (!q.empty()) { auto curr = q.front(); // 取出队首元素 q.pop(); for (int i = 0; i < 4; i++) { int nx = curr.first + dx[i]; int ny = curr.second + dy[i]; if (isValid(nx, ny, m, n, k, visited)) { visited[nx][ny] = true; q.push({nx, ny}); count++; } } } return count; } int main() { int m, n, k; cin >> m >> n >> k; cout << movingCount(m, n, k) << endl; return 0; }
代码注释说明:
● 主函数movingCount中,先判断输入合法性,避免无效参数导致错误。
● 使用方向数组dx、dy简化四方向偏移计算,提升代码可读性。
● 通过visited矩阵避免重复遍历,保证BFS正确性。
五、总结
该解法通过BFS算法结合自定义的数字各位和计算,高效解决网格可达点问题。时间复杂度为O(mn),空间复杂度为O(mn),适用于中等规模的网格场景。关键点在于合理设计辅助函数与边界判断,避免无效计算。实际应用中,可扩展至其他基于坐标限制的搜索问题,具有一定通用性。
原创内容 转载请注明出处