坠落的蚂蚁

坠落的蚂蚁

题目描述:
一根长度为1米的木棒上有若干只蚂蚁在爬动。它们的速度为每秒一厘米或静止不动,方向只有两种,向左或者向右。如果两只蚂蚁碰头,则它们立即交换速度并继续爬动。三只蚂蚁碰头,则两边的蚂蚁交换速度,中间的蚂蚁仍然静止。如果它们爬到了木棒的边缘(0或100厘米处)则会从木棒上坠落下去。在某一时刻蚂蚁的位置各不相同且均在整数厘米处(即1,2,3,…99厘米),有且只有一只蚂蚁A速度为0,其他蚂蚁均在向左或向右爬动。给出该时刻木棒上的所有蚂蚁位置和初始速度,找出蚂蚁A从此时刻到坠落所需要的时间。

输入描述:
第一行包含一个整数表示蚂蚁的个数N(2<=N<=99),之后共有N行,每一行描述一只蚂蚁的初始状态。每个初始状态由两个整数组成,中间用空格隔开,第一个数字表示初始位置厘米数P(1<=P<=99),第二个数字表示初始方向,-1表示向左,1表示向右,0表示静止。

输出描述:
蚂蚁A从开始到坠落的时间。若不会坠落,输出“Cannot fall!”

输入:
4
10 1
90 0
95 -1
98 -1
输出:
98

题解:本题最终要的是要理解,一个蚂蚁只会在他左右两边的蚂蚁所圈定的范围内活动,也就是说不论怎么运动,这几个蚂蚁在木棒上的相对顺序是不变的。

首先交换速度的含义不仅仅是交换速度的大小,同时也交换了方向。也就是说蚂蚁碰头后并不会越过对方,而是向反方向继续前进。可以理解为:没有谁能越过对方,所有蚂蚁只能在由左右两只蚂蚁组成的“囚笼”内移动。
找到速度为0的蚂蚁
它左边有left个蚂蚁
右边有right个蚂蚁
如果判断蚂蚁最后向左掉下,那么它必定是第left+1个掉下去的
如果向右掉下,那么必定是第right+1个掉下去的

怎么判断从哪边掉下去呢?
设向左走的蚂蚁有 toleft个
向右走的蚂蚁右 toright个
首先要明白 最后的最后 一定会有toleft个蚂蚁从左边落下,toright个蚂蚁从右边落下。

如果所有向左走的蚂蚁的数量toleft大于left那么静止蚂蚁左边的left个都掉下去了,此时还有蚂蚁要从左边掉下去,那么就轮到了静止的蚂蚁了

如果所有向右走的蚂蚁的数量toright大于right那么静止蚂蚁右边的right个都掉下去了,此时还有蚂蚁要从右边掉下去,那么就轮到了静止的蚂蚁了。

如果向左走的蚂蚁toleft等于left那么就轮不到静止的蚂蚁跳下去
如果向右走的蚂蚁toright等于right那么就轮不到静止的蚂蚁跳下去

现在清楚了如果判断从哪边跳下去,那么时间如何计算呢
如果从左边跳下去,那么可以认为是向左走的蚂蚁中,下标为left的蚂蚁从开始位置走到最左边的时间

如果从右边跳下去,那么可以认为是向右走的蚂蚁中,(right=n-1-left)下标为n-left-1的蚂蚁从开始位置走到最右边的时间。


以下为参考代码:

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
 
struct Ant
{
    int position;
    int direct;    //方向
};
bool cmp(Ant a,Ant b)
{
    return a.position<b.position;
}
 
int main()
{
    int n;
    while(scanf("%d",&n) != EOF)
    {
        vector<Ant> ant(n);
        for(int i = 0; i<n; i++)
            scanf("%d %d",&ant[i].position,&ant[i].direct);
        sort(ant.begin(),ant.end(),cmp);
        //接下来要做的就是找到静止的那只的位置,为此我们要先排序
        //这样找到的静止的蚂蚁左边有几只就出来了
        int target,toLeft = 0;    //这里选用向左走的为基准来做
        for(int i = 0; i<n; i++)    //遍历所有蚂蚁
        {
            if(ant[i].direct == 0)
                target = i;
            if(ant[i].direct == -1)
                toLeft++;
        }//现在的target就是静止的蚂蚁左边的数量了,也就是静止蚂蚁的下标
        bool flag = false;
        int ans;
        if(toLeft == target)
            flag = true;
        else if (toLeft > target)//这样的话我们要找的就是所有向左走的蚂蚁中,下表为target的蚂蚁
        {
            int cnt = 0;//计数器
            for(int i = 0; i<n; i++)
            {
                if(ant[i].direct == -1 && cnt == target)
                {
                    ans = ant[i].position;//这只蚂蚁的位置,即为它坠落所需的时间,也就是蚂蚁A坠落的时间
                    break;
                }
                else if(ant[i].direct == -1)
                    cnt++;
            }
        }
        else    //向左走的蚂蚁少,那么目标蚂蚁会向右落下
        {
            int cnt = 0;
            for(int i = n - 1; i>=0; i--)
            {
                if(ant[i].direct == 1 && cnt == n - target - 1)//相应的变化,cnt要变成静止蚂蚁右边的蚂蚁数量
                {
                    ans = 100 - ant[i].position; //由于是向右,就用100减一下
                    break;
                }
                else if(ant[i].direct == 1)
                    cnt++;
            }
        }
        if(flag)
            printf("Cannot fall!\n");
        else
            printf("%d\n",ans);
    }//while
    return 0;
}

废了不少时间才想明白,趁着还没忘,赶紧记下来。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值