1. 问题描述:
奶牛贝茜正在参加冬季哞林匹克运动会的越野滑雪比赛。她以每秒 1 米的速度出发。但是,随着时间的推移,她变得越来越疲倦,她开始放慢脚步。每次放慢脚步,贝茜的速度都会降低:减速一次后,她以每秒 1/2 米的速度移动,减速两次后,则以每秒 1/3 米的速度移动,依此类推。
你将被告知何时何地贝茜会减速。当减速信息格式为:
T 17
意味着,贝茜在某个时间点减速,本例表示比赛开始第 17 秒贝茜减速。当减速信息格式为:
D 10
意味着,贝茜在某个地点减速,本例表示在行进 10 米处减速。给定 N 个减速信息,请计算贝茜滑完一千米需要多少秒。将你的答案四舍五入到最接近的整数( 0.5 向上舍入为 1)。
输入格式
第一行包含整数 N。接下来 N 行,每行描述一个减速信息,格式为 T x 或 D x。无论哪种情况,x 都是一个整数,保证所有减速都在贝茜滑完一千米前发生。可能同时发生多次减速,那么这会使得贝茜的速度一下子变慢很多。所有减速信息不一定按顺序给出。
输出格式
输出贝茜滑完一千米所需的总时间。
数据范围
1 ≤ N ≤ 10000
输入样例:
2
T 30
D 10
输出样例:
2970
样例解释
贝茜以每秒 1 米的速度跑完前 10 米,耗时 10 秒。然后她减速到每秒 1/2 米,接下来的 10 米要花 20 秒。然后她在第 30 秒时,再次减速到每秒 1/3 米。滑完剩下的 980 米需要 980×3=2940 秒。因此,总时间是 10+20+2940=2970 秒。
来源:https://www.acwing.com/problem/content/description/1936/
2. 思路分析:
分析题目可以知道这道题目的难点在于同时存在某个时间点和位置处减速,如果只是存在某个时间点或者某个位置处减速那么问题就变得很简单了直接计算即可,当同时存在时间和位置减速的时候那么需要考虑哪一个事件先发生那么就先处理哪一个事件,所以我们可以先用vector或者list列表按照时间和位置减速的事件存储下来,然后从小到大进行排序,相当于是给出了两个从小到大排序的数轴,数轴上对应两个发生的事件对于先发生的事件那么就需要先处理这些事件,所以本质上是二路归并模型,所以问题的核心就转化为了如何判断数轴上的哪个事件先发生,我们可以比较两个事件发生的时间,对于按照时间减速的记为a,按照位置减速的记为b,所以计算出在位置b[j]处发生的时间,两者分别减去上一段已经走的距离的时间,比较a[i]和b[j]发生的时间先后,如果事件a[i]先发生那么先处理事件a[i],否则处理b[j],并且更新相应的参数,其中涉及到的参数有当前已经走过的距离s,当前的速度的倒数v(速度的倒数比较好处理),走过s花费的时间t,当前在a和b分别对应的位置i和j,因为最终会在1000米处停下来所以可以在b中插入1000这样就很方便处理了。
3. 代码如下:
class Solution:
def process(self):
n = int(input())
# a, b为对应时间和距离减速
a, b = list(), list()
for i in range(n):
s = input().split()
if s[0] == "T":
a.append(int(s[1]))
else:
b.append(int(s[1]))
# 在1000米处截止
b.append(1000)
# 排序
a.sort()
b.sort()
# s为走的距离, t为当前所用的时间, i,j分别为对应时间和位置减速的位置
s = t = i = j = 0
# v为速度的倒数
v = 1
# 二路归并
while i < len(a) or j < len(b):
# 先发生事件a, 那么先处理事件a(j走到了尽头或者是a先发生)
if j == len(b) or i < len(a) and a[i] - t < (b[j] - s) * v:
s += (a[i] - t) / v
t = a[i]
v += 1
i += 1
else:
t += (b[j] - s) * v
s = b[j]
v += 1
j += 1
# 四舍五入不保留小数
return "{:.0f}".format(t)
if __name__ == "__main__":
print(Solution().process())