0812-蓝桥历届试题-蚂蚁感冒

                                                       蚂蚁感冒

描述

长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。 每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。 当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。 这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。 请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。

输入

第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。
接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。

输出

要求输出1个整数,表示最后感冒蚂蚁的数目。

样例输入

3
5 -2 8
5
-10 8 -20 12 25

样例输出

1
3

来源

第五届蓝桥杯


最近出去玩了,因此好长一段时间都没更新,今天本想搞一道简单一点的题,练练手,结果发现自己连初学者做的题都搞不出来了,感到深深的挫败,欸,废话不多说了,讲题

分析

这道题用到了一个非常巧妙的思维转换,因为两只蚂蚁碰面后该感冒的全感冒,没有感冒的也没有感冒,而且速度也一样,只是要掉头,而掉头实际上可以看作两只蚂蚁对穿而过,明确这一点后就很好做了。我们就不用考虑掉头了

我们发现对于第一只蚂蚁(就是那只感冒的),它左边的那些蚂蚁,如果有往右走的,最终一定会感冒,而它右边的蚂蚁,如果有往左走的也一定会感冒,那么答案就是 ans = right + left + 1 (别忘了第一只)。最后特判一下全部往左和全部往右的情况,输出 1 即可

我们再来仔细研究一下这个算法的正确性:

不用考虑第一只蚂蚁的方向---这是因为只要不是全右或全左,这只蚂蚁往左走,就会碰到一只向右的蚂蚁,那么无论你是看作对穿而过还是掉头,都会有一只感冒的蚂蚁一直往右走,那么向左向右都有感冒的蚂蚁了,如果第一只蚂蚁往右走同理,因此不需要考虑第一只蚂蚁的方向

不用考虑在第一只蚂蚁左边或右边的相遇---因为这样的相遇,双方都不可能是感冒的,(毕竟都还没有遇到第一只蚂蚁)


代码

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int n,ans=0;
struct node{
	int cold,pos,dir,num;
}a[55];
bool my(const node &a,const node &b){
	return a.pos<b.pos;
}
int main(){
	scanf("%d",&n);
	int i,j,k;
	bool flagl=1,flagr=1;//特判全左或全右的情况
	memset(a,0,sizeof(a));
	a[1].cold=1;
	for(i=1;i<=n;++i){
		scanf("%d",&k);
		a[i].num=i;
		if(k<0) flagr=0,a[i].dir=-1,a[i].pos=-k;
		else  flagl=0,a[i].dir=1,a[i].pos=k;
	}
	if(flagl||flagr){
		printf("1");
		return 0;
	} 
	sort(a+1,a+n+1,my);
	ans=1;
	for(i=1;i<=n;++i){
		if(a[i].num==1) break;
		if(a[i].dir==1) ans++;
	}
	for(++i;i<=n;++i){
		if(a[i].dir==-1) ans++;
	}
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/81607145