上一次更新还是在一周前!!!一周不更新,一更新拉托大的!!!!
这个题一看就感觉很复杂,重要的是抽丝剥茧,把复杂问题提炼成简单问题。注意题中交换速度的意思是速度的大小和方向都要交换。
这道题里蚂蚁运动的情况需要一点想象力,不好想象的话不妨画个示意图:
![图1](https://i-blog.csdnimg.cn/blog_migrate/8c05457b28977ca3e4f50da6652925a3.jpeg)
这样一番操作下来,相当于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开始推算。