一、题目大意
我们有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;
}