算法策略:广度优先搜索 (BFS)
鉴于我们需要求最少操作次数,且每一步操作的代价均等(权重为1),广度优先搜索 (BFS) 是最优选择。
核心逻辑
- 层级遍历:从初始状态出发,第一层探索 1 步可达的状态,第二层探索 2 步可达的状态,以此类推。首次遇到
的状态时,当前的层数即为最小操作次数。
- 状态去重:使用哈希集合(Visited Set)记录已访问过的
状态,防止因“交换”操作导致的死循环(例如:
)以及重复计算。
- 搜索剪枝/终止条件:
- 由于输入范围极小
,且目标是相等。如果存在解,通常步数很少。
- 随着变换操作,
和
会迅速呈指数级增长。如果数值超过了一定阈值(例如绝对值超过 10,000 或 100,000)仍未找到解,基于上述范数增长的性质,后续也不可能收敛到相等状态(因为数值只会越来越大且保持特定的倍数关系),此时可判定无解。
- 由于输入范围极小
代码实现
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct State {
ll x;
ll y;
ll steps;
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int X, Y;
cin >> X >> Y;
if (X == Y) {
cout << "0\n";
return 0;
}
set<pair<ll, ll>> visited;
queue<State> Q;
const ll LIMIT = 100000;
Q.push({X, Y, 0});
while (!Q.empty()) {
auto [curX, curY, curStep] = Q.front();
Q.pop();
if (curX == curY) {
cout << curStep << "\n";
return 0;
}
pair<ll, ll> op1 = {curY, curX};
if (visited.find(op1) == visited.end()) {
visited.insert(op1);
Q.push({op1.first, op1.second, curStep + 1});
}
ll nextX = curX + curY;
ll nextY = curX - curY;
// 剪枝:检查是否超出合理数值范围
if (abs(nextX) <= LIMIT && abs(nextY) <= LIMIT) {
pair<ll, ll> op2 = {nextX, nextY};
if (visited.find(op2) == visited.end()) {
visited.insert(op2);
Q.push({nextX, nextY, curStep + 1});
}
}
}
cout << "-1\n";
return 0;
}
复杂度分析
1. 时间复杂度
算法的时间复杂度取决于访问的状态总数。
- 理论上状态空间是无限的,但受限于两点:
- 数值增长:变换操作使范数翻倍。对于 32 位整数,约 30 次变换后溢出。对于任何实际有意义的解,步数通常很小。
- 边界剪枝:我们设定了一个数值上限
(例如
)。
- 在范围
内,尽管整数点很多,但从
出发能到达的轨迹是非常稀疏的树状结构。
- 设搜索的最大有效深度为
(受限于数值溢出或阈值,约 20-30)。每一层状态数最多翻倍。
- 实际上,重复状态会被
Visited集合过滤。对于小范围输入,有效状态数
远小于网格总点数。
- 时间复杂度:
,其中
是到达边界
或目标之前的可达状态数。对于本题约束,这是一个很小的常数级计算量。
2. 空间复杂度
- 空间复杂度:
。
- 需要存储
Visited集合和 BFS 队列。空间消耗与访问的状态数量成正比。

京公网安备 11010502036488号