KY89 坠落的蚂蚁!!!!

上一次更新还是在一周前!!!一周不更新,一更新拉托大的!!!!

这个题一看就感觉很复杂,重要的是抽丝剥茧,把复杂问题提炼成简单问题。注意题中交换速度的意思是速度的大小和方向都要交换。

这道题里蚂蚁运动的情况需要一点想象力,不好想象的话不妨画个示意图:

图1
图1

这样一番操作下来,相当于A替C跟B碰了一下面,把速度跟B交换了,最后又把交换后的速度还给C,自己继续乖乖被封印。

由此可以大胆推断(如果胆子不够大的话也可以自己再画几个小人):如果在A左边且速度向右的蚂蚁数 == 在A右边且速度向左的蚂蚁数,则A总是解封一下来回走走又被封印住,掉不下木棒。

那么如果只关注A的一侧呢?

左边是BD交换速度的情况,右边是BD不交换速度的情况。我们可以看到,无论BD交换不交换速度的方向,对A的影响都是不变的,即一只蚂蚁靠近A,一只蚂蚁远离A。而到底是哪只蚂蚁靠近A,哪只蚂蚁远离A其实不重要。所以只要别的蚂蚁不与A发生交互使A的速度改变,他们之间交换速度方向可以直接等效于根本没有交换速度方向,而是彼此擦肩而过、互不干扰,这大大简化了问题的复杂度。 这道题就简化成了谁跟A撞到就和A交换速度,其他BCDEFG蚂蚁之前互不打扰。

我们用新的题干再来看一下这个问题:首先,在A左边且速度方向向左的蚂蚁,与在A左边且速度方向向右的蚂蚁擦肩而过,走向木棍0端然后陆续掉下;在A右边速度方向向右的蚂蚁,与在A右边速度方向向左的蚂蚁擦肩而过,走向木棍100端然后陆续掉下。换言之,这两种蚂蚁都可以不用管了,对A不会有影响的。

剩下的对A可能有影响的蚂蚁就是在A两侧的走向A的蚂蚁,由于图1的分析可得,一对在A两侧相向而行的蚂蚁,在先后和A交换速度后,结局是A仍然被封印,两侧的蚂蚁远离而去,最终掉下木棍。

假设A左边有两只向右的蚂蚁,A右边有两只向左的蚂蚁,最终可以预见的结果是:这些蚂蚁成对交换速度方向,A仍被封印,这四只最终走向木棒端部。

假设A左边有两只向右的蚂蚁,A右边有只向左的蚂蚁,最终可以预见的结果是:有四只蚂蚁成对交换速度方向,最终走向端部,还有一只与A相碰后被A封印,然后A继承它的衣钵(即速度),继续前行,由于此时A已经碰不到与它相向而行的蚂蚁了,所以A走到端部后掉落。

那么A从被 第一只 无法与对面成对交换速度 而被A封印的 蚂蚁碰到,到掉下木棒要多久呢?

把A的左右两边的蚂蚁装入两个数组(只讨论对A有影响的蚂蚁,即在A两侧的走向A的蚂蚁),方向向左的录入l数组,方向向右的录入r数组。数组内元素按位于木棍上的坐标位置从小到大排列,如下图所示。

斜线划掉的是成对交换速度后远离A的蚂蚁,剩下的第一只靠近A的蚂蚁是l组4号,它就是改变A命运的真神,之前的蚂蚁都是遛A来着,只有它是一命换一命。 

真神4号从出发到遇到A再到A复活后继续向左走直至掉下,其实就是接力走了从真神4号到木棒0端的距离,也等于真神4号的坐标大小。4号的“4”是怎么计算出来的呢?(注意:下图的数组下标从0开始)

上面的信息理解了,代码就很容易写了。以下代码是在前人的基础上改写的: 

#include <stdio.h>
#include <stdlib.h>
int cmp(const void *a,const void *b){
	return *(int *)a-*(int *)b;
}
typedef struct ant
{
	int l;
	int v;
}ant;
int main(){
    int n;
	ant anta[101];
	int ll[101];//向左侧移动的蚂蚁
	int lr[101];//向右侧移动的蚂蚁
	int apos;
	while(scanf("%d",&n)==1){
		int lpos=0,rpos=0;
		for(int i=0;i<n;i++){
			scanf("%d %d",&anta[i].l,&anta[i].v);
			if(anta[i].v==0)
				apos=anta[i].l;
		}
		for(int i=0;i<n;i++)
		{
			if(anta[i].l>apos&&anta[i].v==-1)
				ll[lpos++]=anta[i].l;
			if(anta[i].l<apos&&anta[i].v==1)
				lr[rpos++]=anta[i].l;
		}
		qsort(ll,lpos,sizeof(int),cmp);
		qsort(lr,rpos,sizeof(int),cmp);
		if(lpos==rpos)
			printf("Cannot fall!\n");
		else if(lpos>rpos)
			printf("%d",ll[rpos]);
		else 
			printf("%d",100-lr[rpos-lpos-1]);

	}
	return 0;
}

可以积累一下qsort函数。

头文件#include <stdlib.h>

需要先定义函数cmp:

从小到大排列

int cmp(const void *a,const void *b){
    return *(int *)a-*(int *)b;
}

从大到小排列

int cmp(const void *a,const void *b){
    return *(int *)b-*(int *)a;
}

调用时这样写:qsort(数组名,数据个数,sizeof(int),cmp);

调用后的结果就是数组里随意排序的数据变成有序排列的了。

写在后面: 

终于写完了,不容易,这种题我觉得考试的时候直接写出来还是很困难的,一定要有积累。

分析完其实感觉思路也不难,就是很唬人,需要冷静下来慢慢思考,但是限时的考试又紧张压力又大,会让它看起来比实际难度难很多,怪不得是北大复试题。所以这种题平常一定要弄明白思路,考试的时候遇见类似的直接当模板去用,而不是从0开始推算。

  • 47
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值