POJ 2674 Linear world(蚂蚁问题升级版) 弹性碰撞

文章讲述了如何解决一个关于N只蚂蚁在长木板上碰撞的问题,通过判断蚂蚁与边界距离计算最后掉落时间,并确定掉落蚂蚁的编号。作者使用了代码示例和模拟方法来演示解题过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目大意

我们有N只蚂蚁,在长度为L的木板上以相同的速度行进,两只蚂蚁相撞后,它们互相折返,朝着各自相反的方向继续行进。题目要求计算出最后一只蚂蚁掉落的时间,并输出这是哪一只蚂蚁(输出它的名字)

二、解题思路

对于最后一只蚂蚁掉落的时间,其实很容易计算,我们只需要在输入蚂蚁信息的时候,判断下它距离边界的距离,找出最大的即可(如果它是向右,则记录L-pos,如果它是向左,记录pos)。

忽略物块大小且速度大小相同的,弹性碰撞,可以看作擦肩而过。

那么最大的边界间距,除以V,就是最后一只蚂蚁掉落的时间。

我做了一个excel表格,用来模拟26只方向随机的蚂蚁的碰撞关系,用每一行代表一只蚂蚁,用每一列代表每一次碰撞后的状态,将每次碰撞的两只蚂蚁加粗,作图如下所示。

最终发现,在多次碰撞结束的最后状态时,蚂蚁的方向就不会再发生变化

从图中可以很清晰的发现,最后一个从左边掉落的蚂蚁,就是第(N - 初始时向右的蚂蚁数量),最后一个从右边掉落的蚂蚁,就是第(初始时向左的蚂蚁数量+1)个。

然后本题目的一个坑点,输出答案答案要截取TRUNC,而不是四舍五入,所以我对计算的结果*100取整,然后将取整的结果又除以100.0用%13.2f输出才通过。

三、代码

#include <iostream>
#include <cmath>
using namespace std;
struct Node
{
    // 是否向右移动
    bool ifGoForRight;
    // 位置
    double pos;
    // 名字
    char name[300];
    Node() {}
};
Node nodes[32007];
int goForRightCount, goForLeftCount, N;
double L, V, maxDistance, maxDirIsRight;
void input()
{
    goForLeftCount = 0, goForRightCount = 0;
    maxDistance = -1.0, maxDirIsRight = true;
    scanf("%lf%lf", &L, &V);
    char dir;
    for (int i = 1; i <= N; i++)
    {
        scanf("\n%c%lf%s", &dir, &nodes[i].pos, &nodes[i].name);
        nodes[i].ifGoForRight = (dir == 'p' || dir == 'P') ? true : false;
        if (nodes[i].ifGoForRight)
        {
            goForRightCount++;
        }
        else
        {
            goForLeftCount++;
        }
        if (L - nodes[i].pos > maxDistance && nodes[i].ifGoForRight)
        {
            maxDistance = L - nodes[i].pos;
            maxDirIsRight = true;
        }
        if (nodes[i].pos > maxDistance && !nodes[i].ifGoForRight)
        {
            maxDistance = nodes[i].pos;
            maxDirIsRight = false;
        }
    }
}
void findAns()
{
    double ans = maxDistance / V;
    long long maxDistanceLong = ans * 100;
    double realAns = maxDistanceLong / 100.0;
    printf("%13.2f ", realAns);
    if (maxDirIsRight)
    {
        printf("%s\n", nodes[goForLeftCount + 1].name);
    }
    else
    {
        printf("%s\n", nodes[N - goForRightCount].name);
    }
}
int main()
{
    while (true)
    {
        scanf("%d", &N);
        if (N == 0)
        {
            break;
        }
        input();
        findAns();
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值