题目描述
在国际象棋中,骑士的每一步移动是:水平移动两格且垂直移动一格,或水平移动一格且垂直移动两格。
骑士从无限棋盘上的 (0,0)(0,0)(0,0) 出发,走一步能到达以下八个位置之一:
(1,2),(−1,2),(1,−2),(−1,−2),(2,1),(−2,1),(2,−1),(−2,−1)(1,2), (-1,2), (1,-2), (-1,-2), (2,1), (-2,1), (2,-1), (-2,-1)(1,2),(−1,2),(1,−2),(−1,−2),(2,1),(−2,1),(2,−1),(−2,−1)。
给定任意目标位置 (x,y)(x,y)(x,y),求骑士从 (0,0)(0,0)(0,0) 到达该位置所需的最少步数。
输入格式
输入包含多行,每行两个整数 xxx 和 yyy,每个数的绝对值最多为 10910^9109。这些整数表示棋盘上的一个位置 (x,y)(x,y)(x,y)。
输入的最后一行是单词 END。
输出格式
对于输入的每个位置,输出一行,包含一个整数,即骑士从 (0,0)(0,0)(0,0) 到 (x,y)(x,y)(x,y) 所需的最少步数。
样例
输入
1 2
2 4
END
输出
1
2
题目分析
本题是经典的“骑士最短步数”问题,但坐标范围极大(绝对值 ≤109\le 10^9≤109),因此无法使用传统的广度优先搜索(BFS\texttt{BFS}BFS)算法。我们需要利用数学推导,找到一个直接计算最少步数的公式。
骑士的移动具有对称性,因此我们可以将任意目标点 (x,y)(x,y)(x,y) 通过取绝对值和交换坐标,映射到第一象限且满足 a≥b≥0a \ge b \ge 0a≥b≥0 的点 (a,b)(a,b)(a,b),其中 a=max(∣x∣,∣y∣)a = \max(|x|, |y|)a=max(∣x∣,∣y∣),b=min(∣x∣,∣y∣)b = \min(|x|, |y|)b=min(∣x∣,∣y∣)。这样不会改变最少步数。
通过分析骑士在无限棋盘上的移动规律,我们可以发现最少步数主要由 aaa 和 bbb 的比值决定。当 aaa 远大于 bbb 时,骑士可以沿着接近直线的路径前进;当 aaa 和 bbb 接近时,则需要更多的“蛇形”移动。此外,还需要考虑骑士移动的奇偶性约束:每一步都会改变坐标和的奇偶性,因此最终步数的奇偶性必须与 a+ba+ba+b 的奇偶性一致。
解题思路
数学公式推导
对于 a≥b≥0a \ge b \ge 0a≥b≥0,设最少步数为 mmm。经过对大量小范围数据的 BFS\texttt{BFS}BFS 结果进行观察和归纳,可以得到以下结论:
-
特殊点处理:
- 当 (a,b)=(1,0)(a,b) = (1,0)(a,b)=(1,0) 时,答案为 333。因为骑士无法在 111 步内到达 (1,0)(1,0)(1,0),而 222 步也无法到达,最少需要 333 步。
- 当 (a,b)=(2,2)(a,b) = (2,2)(a,b)=(2,2) 时,答案为 444。这也是一个无法用通用公式覆盖的特殊情况。
-
通用公式:
对于其他情况,最少步数 mmm 可以通过以下方式计算:- 首先计算两个下界:
m1=⌈a2⌉ m_1 = \left\lceil \frac{a}{2} \right\rceil m1=⌈2a⌉
这是因为骑士每步在 xxx 方向最多前进 222 格。
m2=⌈a+b3⌉ m_2 = \left\lceil \frac{a+b}{3} \right\rceil m2=⌈3a+b⌉
这是因为骑士每步最多使 a+ba+ba+b 增加 333(例如从 (0,0)(0,0)(0,0) 到 (2,1)(2,1)(2,1),a+b=3a+b=3a+b=3)。 - 取 m=max(m1,m2)m = \max(m_1, m_2)m=max(m1,m2)。
- 然后调整奇偶性:如果 mmm 与 a+ba+ba+b 的奇偶性不同,则 mmm 增加 111。
这是因为骑士每步会改变坐标和的奇偶性,所以 mmm 必须与 a+ba+ba+b 同奇偶。
- 首先计算两个下界:
正确性说明
这个公式来自对骑士距离问题的经典数学分析。在无限棋盘上,骑士的移动可以看作是在二维格点上的一个“步长”问题。通过考虑坐标轴方向和“曼哈顿距离”的约束,可以推导出上述下界。而奇偶性调整则是为了满足棋盘上“黑白染色”的约束条件(骑士每步都会改变所在格子的颜色)。经过对所有小范围数据的验证,该公式在 a,ba,ba,b 较大时完全正确,对于少数小范围特殊点单独处理即可。
复杂度分析
- 每个测试点仅需常数次算术运算,时间复杂度为 O(1)O(1)O(1)。
- 空间复杂度为 O(1)O(1)O(1)。
代码实现
// Knight's Trip
// UVa ID: 11852
// Verdict: Accepted
// Submission Date: 2026-06-17
// UVa Run Time: 0.000s
//
// 版权所有(C)2026,邱秋。metaphysis # yeah dot net
#include <bits/stdc++.h>
using namespace std;
// 计算骑士从 (0,0) 到 (x,y) 的最少步数
int minKnightMoves(int x, int y) {
int a = max(abs(x), abs(y)); // 较大坐标
int b = min(abs(x), abs(y)); // 较小坐标
// 两个特殊点,公式不适用
if (a == 1 && b == 0) return 3;
if (a == 2 && b == 2) return 4;
// 下界取较大值
int d = max((a + 1) / 2, (a + b + 2) / 3);
// 调整奇偶性,使步数与 (a+b) 同奇偶
if ((d + a + b) % 2 != 0) ++d;
return d;
}
int main() {
string token;
while (cin >> token) {
if (token == "END") break;
int x = stoi(token);
int y;
cin >> y;
cout << minKnightMoves(x, y) << '\n';
}
return 0;
}
总结
本题的核心在于利用数学推导直接计算骑士在无限棋盘上的最短步数,避免了在大坐标下无法使用 BFS\texttt{BFS}BFS 的困境。解题的关键是:
- 对称性简化:将任意点映射到第一象限且满足 a≥ba \ge ba≥b。
- 下界估计:从坐标轴方向和“曼哈顿距离”增长速率两个角度给出步数的下界。
- 奇偶性修正:利用骑士移动改变坐标和奇偶性的性质,调整步数使其合法。
这种“数学公式 + 特殊点处理”的策略在大范围坐标问题中非常常见,值得积累和掌握。对于这类问题,通过小范围数据发现规律,再结合理论分析推导公式,是高效且准确的解题方式。

216

被折叠的 条评论
为什么被折叠?



