蚂蚁感冒
题目描述
长 100 厘米的细长直杆子上有 nn 只蚂蚁。它们的头有的朝左,有的朝右。
每只蚂蚁都只能沿着杆子向前爬,速度是 1 厘米/秒。
当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。
这些蚂蚁中,有 1 只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。
请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
输入描述
输入描述
第一行输入一个整数 n (1<n<50)n (1<n<50), 表示蚂蚁的总数。
接着的一行是 nn 个用空格分开的整数 Xi (−100<Xi<100)Xi (−100<Xi<100),XiXi 的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现 0 值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。
输出描述
要求输出 1 个整数,表示最后感冒蚂蚁的数目。
输入输出样例
示例
输入
3
5 -2 8
输出
1
运行限制
- 最大运行时间:1s
- 最大运行内存: 256M
总通过次数: 1592 | 总提交次数: 1779 | 通过率: 89.5%
难度: 中等 标签: 2014, 模拟, 思维, 省赛
方法思路
题目要求计算当所有蚂蚁爬离杆子时,感冒的蚂蚁数量。关键点在于理解蚂蚁相遇时的行为:它们会掉头,并且感冒会传染。通过分析,可以得出以下结论:
相遇行为分析:当两只蚂蚁相遇时,它们会掉头,但可以等价地视为它们继续沿原方向前进(即穿过对方),同时感冒会传染。这种等价模型简化了问题,因为蚂蚁的路径和最终感冒的蚂蚁数量不变。
感冒传播规律:
初始感冒的蚂蚁(设为A)向右移动(正方向)时:
它会传染所有在它右侧(位置绝对值大于A)且向左移动(负方向)的蚂蚁。
如果存在上述被传染的蚂蚁,那么这些蚂蚁会继续传染在它们左侧(位置绝对值小于被传染蚂蚁)且向右移动的蚂蚁。
因此,感冒的蚂蚁数量为:1(A) + 右侧向左的蚂蚁数 + 左侧向右的蚂蚁数(当存在右侧向左蚂蚁时)。
如果没有右侧向左的蚂蚁,则只有A感冒。
初始感冒的蚂蚁向左移动(负方向)时:
它会传染所有在它左侧(位置绝对值小于A)且向右移动(正方向)的蚂蚁。
如果存在上述被传染的蚂蚁,那么这些蚂蚁会继续传染在它们右侧(位置绝对值大于被传染蚂蚁)且向左移动的蚂蚁。
因此,感冒的蚂蚁数量为:1(A) + 左侧向右的蚂蚁数 + 右侧向左的蚂蚁数(当存在左侧向右蚂蚁时)。
如果没有左侧向右的蚂蚁,则只有A感冒。
#include <iostream> #include <cmath> using namespace std; int main() { int n; cin >> n; int a[50]; for (int i = 0; i < n; i++) { cin >> a[i]; } int left = 0, right = 0; int first = a[0]; for (int i = 1; i < n; i++) { // 统计在感冒蚂蚁左侧且向右移动的蚂蚁 if (abs(a[i]) < abs(first) && a[i] > 0) { left++; } // 统计在感冒蚂蚁右侧且向左移动的蚂蚁 if (abs(a[i]) > abs(first) && a[i] < 0) { right++; } } int result; if (first > 0) { if (right == 0) { result = 1; } else { result = 1 + left + right; } } else { if (left == 0) { result = 1; } else { result = 1 + left + right; } } cout << result << endl; return 0; }
代码解释
输入处理:读取蚂蚁数量
n
和每只蚂蚁的位置及方向(正数表示向右,负数表示向左)。统计关键蚂蚁数量:
left
:统计在感冒蚂蚁左侧(位置绝对值小于感冒蚂蚁)且向右移动的蚂蚁数量。right
:统计在感冒蚂蚁右侧(位置绝对值大于感冒蚂蚁)且向左移动的蚂蚁数量。
根据感冒蚂蚁方向计算结果:
如果感冒蚂蚁向右移动(
first > 0
):若右侧没有向左移动的蚂蚁(
right == 0
),则只有它自己感冒(结果=1)。否则,结果为
1 + left + right
(自己 + 左侧向右蚂蚁 + 右侧向左蚂蚁)。
如果感冒蚂蚁向左移动(
first < 0
):若左侧没有向右移动的蚂蚁(
left == 0
),则只有它自己感冒(结果=1)。否则,结果为
1 + left + right
(自己 + 左侧向右蚂蚁 + 右侧向左蚂蚁)。
输出结果:打印最终感冒的蚂蚁数量。