[蓝桥杯][历届试题]蚂蚁感冒

题目

题目链接

题解

思路一:细分+模拟

直接暴力枚举每一秒,修改每个蚂蚁的位置和方向。
但是需要注意,假如两个蚂蚁坐标相邻,那么经过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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值