题目描述
一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为1厘米/秒。
当两只蚂蚁相撞时,二者同时掉头(掉头时间忽略不计)。
给出每只蚂蚁的初始位置和朝向,计算T秒之后每只蚂蚁的位置。
输入格式
输入的第一行为数据组数。每组数据的第一行为3个正整数L,T,n(0<=n<=10000);
以下n行每行描述一致蚂蚁的初始位置,其中整数x为蚂蚁距离木棍左端的距离,字母表示初始朝向(L表示左,R表示右)
输出格式
对于每组数据输出n行,按输入顺序输出每只蚂蚁的位置和朝向(Turning表示正在碰撞)。在第T秒之前已经掉下木棍的蚂蚁(正好爬到木棍边缘的不算)输出Fell off。
分析:
假设在远处观察这些蚂蚁的运动,会看到什么?一群密密麻麻的小黑点在移动。由于黑点太小,所以当蚂蚁因碰撞而掉头时,看上去和两个点“对穿而过”没有任何区别。
如果把蚂蚁看成没有区别的小点,那么只需独立计算出每只蚂蚁在T时刻的位置即可。
比如,有3只蚂蚁,蚂蚁1=(1,R),蚂蚁2=(3,L),蚂蚁3=(4,L)。则两秒钟之后,3只蚂蚁分别为(3,R),(1,L)和(2,L)。
虽然从整体上讲,“掉头”等价于“对穿而过”,但对于每只蚂蚁而言并不是这样。
蚂蚁1初始状态为(1,R),因此一定有一只蚂蚁在两秒钟之后处于(3,R)的状态,但这只蚂蚁却不一定是蚂蚁1。需要搞清楚目标状态中“谁是谁”。
所有蚂蚁的相对顺序是保持不变的,因此把所有目标位置从小到大排序,则从左到右的每个位置对应于初始状态下从左到右的每只蚂蚁。
但蚂蚁不一定按照从左到右的顺序输入,还需要预处理计算出输入中的第i只蚂蚁的序号order[i]。
Python代码:(这个代码写的有些复杂,不够优雅)
before=[[]]*10000
after=[[]]*10000
#方向
dirName=["L","Turning","R"]
order=[0]*10000#输入的第i只蚂蚁是终态中的左数第order[i]只蚂蚁
K=int(input())
for k in range(1,K+1):
print(f"Case {k}")
L,T,n=map(int,input().split())
for i in range(n):
#P代表位置,C代表朝向
INPUT=input().split()
p,c=int(INPUT[0]),INPUT[1]
#d朝向,-1左,1右
d=(-1 if c=='L' else 1)
before[i]=[i,p,d]#i代表输入顺序
after[i]=[0,p+T*d,d]#这里的id是未知的
before=[x for x in before if x]
before.sort(key=lambda x: x[1])
# print(before)
for i in range(n):
order[before[i][0]]=i
#计算终态
after=[x for x in after if x]
after.sort(key=lambda x: x[1])
for i in range(n-1):#修改碰撞中蚂蚁的方向
if after[i][1]==after[i+1][1]:
after[i+1][2]=0
after[i][2]=0
#输出结果
print(f"Case {k} :输出")
for i in range(n):
a=order[i]
if(after[a][1]<0) or (after[a][1]>L):
print("Fell off")
else:
print(after[a][1],dirName[after[a][2]+1])
print("\n")
运行结果: