牛客12546题:广度优先搜索(BFS)解法解决饥饿的小易问题

一、题目解读
牛客12546题是一道典型的数学问题,要求通过给定的数学变换规则(即 x -> (4x+3) % MOD 和 x -> (8x+7) % MOD),从初始位置 x0 出发,寻找到达目标位置(即 x % MOD == 0)的最小步数。题目考察了算法设计中的搜索策略与状态优化,需要高效地遍历状态空间并避免重复计算。
二、解题思路
解题的核心在于采用广度优先搜索(BFS)算法。由于题目要求找到最短路径,BFS天然适合解决此类问题:它按层遍历,确保第一次到达目标状态时的步数即为最小步数。
关键在于:
1. 使用队列存储待扩展的状态(位置+步数)。
2. 哈希表(unordered_map)记录已访问位置,避免重复遍历。
3. 对每个位置生成两个子状态,检查合法性后入队。
4. 设置最大步数限制(MAX_STEPS)防止超时,超出则终止搜索。
5. 终止条件:当位置 x 满足 x % MOD == 0 时,立即输出步数。
三、解题步骤
1. 初始化:将初始位置 x0 入队,标记为已访问,步数为0。
2. 循环扩展:
○ 弹出队首元素 (x, steps)。
○ 计算两个新位置 next1 = (4x+3) % MOD 和 next2 = (8x+7) % MOD。
○ 若新位置未被访问且步数未超限,标记并加入队列(步数+1)。
3. 终止判断:若当前位置满足目标条件,输出步数并结束;若队列为空且未找到目标,输出-1。
四、代码与注释
#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
const long long MOD = 1000000007; // 模数
const int MAX_STEPS = 100000; // 最大步数限制
int main() {
long long x0;
cin >> x0; // 输入初始位置
queue<pair<long long, int>> q; // 存储位置-步数对
unordered_map<long long, bool> visited; // 记录已访问位置
q.push({x0, 0}); // 初始状态入队
visited[x0] = true; // 标记已访问
while (!q.empty()) {
auto current = q.front(); // 获取队首元素
q.pop();
long long x = current.first; // 当前位置
int steps = current.second; // 当前步数
// 目标状态判断
if (x % MOD == 0) {
cout << steps << endl; // 输出最小步数
return 0;
}
// 步数超限,跳过
if (steps >= MAX_STEPS) {
continue;
}
// 生成两个新位置
long long next1 = (4 * x + 3) % MOD;
long long next2 = (8 * x + 7) % MOD;
// 检查并扩展新状态
if (!visited[next1]) {
visited[next1] = true;
q.push({next1, steps + 1});
}
if (!visited[next2]) {
visited[next2] = true;
q.push({next2, steps + 1});
}
}
// 未找到目标,输出-1
cout << -1 << endl;
return 0;
}注释说明:
● MOD 为模数,避免整数溢出。
● MAX_STEPS 限制搜索深度,防止无限循环。
● visited 哈希表优化时间复杂度至O(n),避免重复计算。
● 双状态生成 (4x+3) 和 (8x+7) 符合题目规则。
五、总结
该解法通过BFS结合哈希表,实现了高效的状态遍历与去重,时间复杂度为O(n),空间复杂度为O(n)。优化点包括:
1. 明确终止条件,避免无效搜索。
2. 模运算确保状态合法性。
3. 最大步数限制提升鲁棒性。
适用于求解最短路径类问题,为同类算法设计提供了参考模板。
原创内容 转载请注明出处






