蓝桥杯 蚂蚁感冒

问题描述
  长100厘米的细长直杆子上有n只蚂蚁。它们的头有的朝左,有的朝右。

  每只蚂蚁都只能沿着杆子向前爬,速度是1厘米/秒。

  当两只蚂蚁碰面时,它们会同时掉头往相反的方向爬行。

  这些蚂蚁中,有1只蚂蚁感冒了。并且在和其它蚂蚁碰面时,会把感冒传染给碰到的蚂蚁。

  请你计算,当所有蚂蚁都爬离杆子时,有多少只蚂蚁患上了感冒。
输入格式
  第一行输入一个整数n (1 < n < 50), 表示蚂蚁的总数。

  接着的一行是n个用空格分开的整数 Xi (-100 < Xi < 100), Xi的绝对值,表示蚂蚁离开杆子左边端点的距离。正值表示头朝右,负值表示头朝左,数据中不会出现0值,也不会出现两只蚂蚁占用同一位置。其中,第一个数据代表的蚂蚁感冒了。
输出格式
  要求输出1个整数,表示最后感冒蚂蚁的数目。
样例输入
3
5 -2 8
样例输出
1
样例输入
5
-10 8 -20 12 25
样例输出

3


——————————————————————————————————————————————————————————————————————————————————————————————————————


刚开始想这道题时晕头转向的,满脑子都是碰到一起又掉头回去的蚂蚁,但是只要思维转换一下,把题目描述的情况等效为另一种情况,一切就会豁然开朗了。这种情况就是两只蚂蚁碰见后不会往相反方向爬行,而是直接穿透过去,朝着原方向爬行。

这样一来,我们只需要考虑两种会被传染的情况:

  1. 与最初感冒的蚂蚁相向爬行的蚂蚁会被传染,而最初感冒的蚂蚁所面向的同向爬行的蚂蚁,由于速度一样而且也不会掉头,所以不会被传染。
  2. 如果存在与最初感冒的蚂蚁相向爬行的蚂蚁,那么这只蚂蚁会被传染,则初感冒的蚂蚁身后相向爬行的蚂蚁也会因此被感染到。

根据第一只蚂蚁爬行的方向,将上面两点再分为向左和向右分别考虑。具体的算法步骤首先是将存储有每个蚂蚁位置信息的元素,按从小到大排序好,如果第一个被感染的蚂蚁是向左爬行的,则从最左边的蚂蚁开始,一直到第一个被感染的蚂蚁的位置,统计有几个是向右爬行的蚂蚁,这几只蚂蚁都会被感染。如果存在有向右爬行被感染的蚂蚁,再从第一个被感染的蚂蚁的位置到最右边的蚂蚁,统计有几只是向左爬行的蚂蚁,他们也都会被感染。如果第一个被感染的蚂蚁是向右爬行的,上述步骤则相反。


代码写起来不多,来看一下:

#include<iostream>
#include<algorithm>
using namespace std;
struct node{
	int num; //记录蚂蚁位置 
	bool right;// 记录蚂蚁爬行的方向,true表示向右爬行,false表示向左爬行 
}Nx[60];
bool cmp(struct node c1,struct node c2) 
{
	if(c1.num < c2.num)//sort函数中,按从小到大排列的规则 
	{
		return true;
	}else{
		return false;
	}
}
int main()
{
	int n,i,temp;
	int count = 1; 
	bool flag = false; 
	cin >> n;
	cin >> temp;   //用NX[0]存储第一个感冒的蚂蚁 
	if(temp>0)
	{
		Nx[0].num = temp;
		Nx[0].right  = true;
	}else{
		Nx[0].num = -temp;
		Nx[0].right  = false;
	}
	
	for(i=1;i<n;i++)
	{
		cin >> temp;
		if(temp>0)
	    {
	     	Nx[i].num = temp;
	    	Nx[i].right  = true;
	    }else{
		    Nx[i].num = -temp;
		    Nx[i].right  = false;
	    }
	}
	//将所有储存蚂蚁信息的元素按从小到大的顺序排列(第一个感冒的蚂蚁不参与排列,以免不方便确定哪个是第一个感冒的蚂蚁)
	sort(Nx+1,Nx+n,cmp); 
	if(!Nx[0].right)//如果感冒的蚂蚁向左走 
	{
		i=1;
		while(Nx[0].num > Nx[i].num && i<n)
		{
			if(Nx[i].right)//向左走的感冒的蚂蚁左侧向右走的蚂蚁会被感染 
			{
				count ++ ;
				flag = true;//标记感冒的蚂蚁的右侧向左走的蚂蚁会被感染 
			}
			i++;
		}
		if(flag)
		{
			while(i<n)
			{
				if(!Nx[i].right)//向左走的感冒的蚂蚁右侧向左走的蚂蚁会被感染 
			    {
			    	count ++ ;
		    	}
			    i++;
			}
		} 
	}else{//如果感冒的蚂蚁向右走 
		i=n-1;
		while(Nx[0].num < Nx[i].num && i>0)
		{
			if(!Nx[i].right)//向右走的感冒的蚂蚁右侧向左走的蚂蚁会被感染 
			{
				count ++ ;
				flag = true;//标记感冒的蚂蚁的右侧向左走的蚂蚁会被感染 
			}
			i--;
		}
		if(flag)
		{
			while(i>0)
			{
				if(Nx[i].right)//向右走的感冒的蚂蚁左侧向右走的蚂蚁会被感染 
			    {
			    	count ++ ;
		    	}
			    i--;
			}
		} 
	cout << count; 
	return 0;
}

测试数据更少,才4组

Input:            

5
20 4 -3 -10 -22

Output:3


Input:

10
50 3 4 6 -8 12 -7 11 -60 -65

Output:8


Intput:

10
50 1 2 3 4 5 6 7 8 -59

Output:10


Intput:

10
-50 -10 -20 25 30 35 40 -60 -70 65

Output:7


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值