哈喵~!各位看官,今天我们来解决一道非常可爱的逻辑题,A. Race!这道题就像是在和 Alice 玩一个追逐游戏,我们要帮 Bob 找到一个必胜的位置,是不是很有趣呀?喵~
题目大意
简单来说,就是 Alice 和 Bob 在一条直线上赛跑抢夺奖品的故事,喵。
- Alice 的起点是固定的,在位置
a
。 - 奖品 可能会出现在两个位置中的一个:
x
或者y
。 - Bob 需要选择一个整数点
b
作为他的起点(但是b
不能和 Alice 的起点a
相同)。
我们的任务是,判断 Bob 能否找到这样一个起点 b
,使得无论奖品出现在 x
还是 y
,Bob 到奖品的距离都严格小于 Alice 到奖品的距离。
两个点 c
和 d
之间的距离就是 |c - d|
啦。
如果 Bob 能找到这样的必胜起点,我们就输出 "YES",否则就输出 "NO",喵。
题解方法
这道题的核心在于理解 Bob 的“必胜”条件。他需要找到一个点 b
,同时满足下面两个不等式:
|b - x| < |a - x|
(如果奖品在x
,Bob 比 Alice 更近)|b - y| < |a - y|
(如果奖品在y
,Bob 比 Alice 更近)
让我们把这个问题放到一维的数轴上来思考,这样就直观多啦,喵~
为了方便分析,我们可以先对 x
和 y
的位置进行排序。比如说,我们总是假设 x < y
。如果输入的 x > y
,我们只要把它们交换一下,问题本质是完全一样的,但我们的思考过程可以简化不少哦!
现在,我们有了 x < y
这个前提,再来考虑 Alice 的位置 a
和 x
、y
的相对关系。这里就出现了两种主要情况:
情况一:Alice 的起点 a
在两个奖品点 x
和 y
之间 (也就是 x < a < y
)
- 想象一下,
x
在a
的左边,y
在a
的右边。 - 为了比 Alice 更靠近
x
,Bob 必须选择一个在a
左侧,并且离x
更近的点。这些点都在x
和a
的中点(x+a)/2
的左边。 - 为了比 Alice 更靠近
y
,Bob 必须选择一个在a
右侧,并且离y
更近的点。这些点都在y
和a
的中点(y+a)/2
的右边。
Bob 需要同时满足这两个条件,但是一个点 b
不可能同时在 a
的左边和右边呀!所以,如果 Alice 处在 x
和 y
中间,她就像一个守门员,把通往两个奖品的近路都给分开了。Bob 找不到任何一个位置 b
能同时满足两个条件。所以这种情况下,答案是 "NO",喵呜~。
情况二:Alice 的起点 a
在两个奖品点 x
和 y
的外侧
因为我们已经假设了 x < y
,所以这种情况就包含了 a < x < y
和 x < y < a
两种。
- 如果
a < x < y
: 两个奖品点都在 Alice 的右边。Alice 要跑去x
或者y
,都得往右跑。Bob 只要选择一个在 Alice 和奖品之间的位置,比如b = x
,就可以占得先机啦!- 当奖品在
x
,Bob 的距离是|x - x| = 0
,Alice 的距离是|a - x| > 0
。Bob 赢! - 当奖品在
y
,Bob 的距离是|x - y|
,Alice 的距离是|a - y|
。因为a < x < y
,所以x
比a
更靠近y
,所以|x - y| < |a - y|
。Bob 又赢了!
- 当奖品在
- 如果
x < y < a
: 两个奖品点都在 Alice 的左边。情况和上面类似,Bob 只要选择一个在 Alice 和奖品之间的位置,比如b = y
,也一定能赢。
在这两种子情况下,Bob 总能找到一个必胜点。所以,只要 Alice 不在 x
和 y
之间,答案就是 "YES",喵!
总结一下我们的策略就是:
- 为了方便,先让
x
成为x
和y
中较小的那个。 - 判断
a
是否在x
和y
之间。 - 如果在,就是 "NO";如果不在,就是 "YES"。
是不是很简单呀?喵~
题解
下面是这个思路的 C++ 实现代码,加上了猫娘的专属注释哦!
#include <iostream>
#include <algorithm> // 用来调用 std::swap,很方便喵
#include <cmath> // 用来调用 abs,虽然这里用不到,但是好习惯!
void solve() {
int a, x, y;
std::cin >> a >> x >> y;
// 为了方便,我们让 x 总是比 y 小喵~
// 这样就不用分 x<y 和 y<x 两种情况讨论啦
if (x > y) {
std::swap(x, y);
}
// 现在我们能保证 x <= y
// 根据我们上面的分析,只要 Alice 不在两个奖品点之间,Bob 就有必胜策略
// a > x && a < y 就表示 a 在 x 和 y 之间(因为题目保证了 a,x,y 两两不同)
if (a > x && a < y) {
// Alice 守住了中间,Bob 没办法两头兼顾,好可惜喵...
std::cout << "NO\n";
} else {
// Alice 在外侧,Bob 可以轻松找到一个好位置!耶!
std::cout << "YES\n";
}
}
int main() {
// 这两行是加速输入输出的魔法,对付大数据量很有用喵
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
知识点介绍
这道题虽然简单,但背后也藏着一些有用的知识点呢,喵!
绝对值与数轴距离 (Absolute Value and Distance on a Number Line) 题目中的距离
|c - d|
是一个基础但非常重要的数学概念。它表示在数轴上点c
和点d
之间的距离。理解这一点是解决所有一维坐标问题的基础。分类讨论 (Casework) 这是算法竞赛中一种极其常用的思想。当一个问题看起来比较复杂时,我们可以根据输入数据的某些关键性质将其分解为几个更简单、更清晰的子问题。在这道题里,我们就是根据
a
相对于x
和y
的位置(在中间还是在外侧)进行了分类,从而让问题迎刃而解。简化问题 (Problem Simplification) 通过
std::swap
操作,我们确保了x <= y
。这并不是必须的,但它能让我们的逻辑判断变得更简单(从(a > x && a < y) || (a > y && a < x)
简化为a > x && a < y
)。在解决问题时,先对输入进行预处理或规范化,常常能大大降低代码的复杂性,减少出错的可能,是个非常好的习惯喵!
希望这篇题解对你有帮助喵!如果还有其他问题,随时可以再来找我哦!下次再见啦~ (ฅ'ω'ฅ)