题目
题解
思路一:细分+模拟
直接暴力枚举每一秒,修改每个蚂蚁的位置和方向。
但是需要注意,假如两个蚂蚁坐标相邻,那么经过0.5秒二者相遇,就没法判断了。
因此,我们采用“细分”的思想,即相当于在每两个相邻坐标又添加了一个坐标,比如,两只蚂蚁分别位于5和6,当我们细分后,两只蚂蚁分别位于10和12,这样我们在模拟的时候相当于在枚举每0.5秒,也就是运动0.5cm,二者在11处相遇,不会出现小数的情况了。
(有能力的话,你也可以证明一下:细化后,不会存在某两只蚂蚁相遇点为非整数坐标位置。)
当全部蚂蚁都爬出杆(细化后的杆长为200),循环结束。
遍历统计被感染的蚂蚁的个数。
思路二:思维
因为蚂蚁相遇后会掉头且蚂蚁的速度都相同,那我们不妨理解为蚂蚁相遇不会发生掉头,即从始至终各走各的,互不干扰,按初始方向爬行直至出杆。虽然不会掉头,但是相遇还是会相互感染的。
因此我们可以推断出:
以母体(初始被感染的蚂蚁)为中心,初始位置位于其左侧且初始方向向右的蚂蚁数目不为0时,初始位置位于母体右侧且初始方向向左的蚂蚁全部会被感染;初始位置位于其右侧且初始方向向左的蚂蚁数目不为0时,初始位置位于母体左侧且初始方向向右的蚂蚁全部会被感染。
计算出母体左侧向右爬行的蚂蚁个数和母体右侧爬行的蚂蚁个数后就很容易得到结果了。
注意:即使不考虑一侧为0时才进行统计的要求,仍可以AC(数据太水)
代码1
#include<bits/stdc++.h>
using namespace std;
struct Ant{
int pos, dir, aff, out; // 坐标,方向,是否被感染,是否在杆上
};
bool cmp(Ant a, Ant b) {
return a.pos < b.pos;
}
int n, x, ans, cnt;
Ant ant[55];
int main()
{
scanf("%d", &n);
for(int i = 1;i <= n;i ++) {
scanf("%d", &x);
ant[i].dir = x>0;
ant[i].pos = 2*abs(x);
ant[i].aff = 0;
ant[i].out = 0;
}
ant[1].aff = 1;
sort(ant+1, ant+n+1, cmp);
while(1) {
for(int i = 1;i <= n;i ++) {
if(!ant[i].out) {
if(ant[i].dir) ant[i].pos ++;
else ant[i].pos --;
if(ant[i].pos<=0 || ant[i].pos>=200) ant[i].out=1, cnt++;
}
}
if(cnt == n) break;
for(int i = 1;i < n;i ++) {
if(ant[i].pos == ant[i+1].pos && !ant[i].out && !ant[i+1].out) {
ant[i].dir ^= 1; ant[i+1].dir ^= 1;
if(ant[i].aff || ant[i+1].aff)
ant[i].aff = ant[i+1].aff = 1;
}
}
}
for(int i = 1;i <= n;i ++) if(ant[i].aff) ans ++;
printf("%d", ans);
return 0;
}
代码2
#include<bits/stdc++.h>
using namespace std;
int n, x, ant, cntl, cntr, ans = 1, dir;
int main()
{
cin>>n>>x;
dir = x>0;
x = abs(x);
for(int i = 0;i < n-1;i ++) {
cin>>ant;
if(abs(ant) > x && ant<0) cntr ++;
if(abs(ant) < x && ant>0) cntl ++;
}
if(dir&&cntr) ans += cntl + cntr;
if(!dir&&cntl) ans += cntl + cntr;
cout<<ans<<endl;
// cout<<cntl+cntr+ans<<endl; // 不进行上面的判断直接输出也AC,但是通过样例“5 5 4 3 2 1”的样例输入可知其实是错误的
return 0;
}