LC 2188. 完成比赛的最少时间

https://leetcode-cn.com/contest/weekly-contest-282/problems/minimum-time-to-finish-the-race/

这题有两个关键点,一个关键点考虑清楚了对时间复杂度有把握,另外一个就是对实现细节有帮助。

如果一直使用某个轮胎的话,那么肯定会存在某个时间点应该放弃。并且这个时间点并不会很长,因为 `r >= 2` 而 `changeTime <= 10^5`. 如果两次耗时超过 `changeTime + f` 的话,那么完全可以直接丢弃这个轮胎,使用这个新轮胎。为了保险起见,可以将这个时间点定在 `T=20` 次之后。

另外一个就是,如果我们认为第一次使用就考虑 `changeTime` 的话,那么之后叠加起来就会更加容易。得到结果之后,减去第一次的 `changeTime` 就好了。

最终我们可以得到 `best[T]` 表示跑T圈的最短耗时是多少,然后就是一个动态规划问题。

class Solution:
    def minimumFinishTime(self, tires: List[List[int]], changeTime: int, numLaps: int) -> int:
        n = len(tires)
        cost = [changeTime] * n
        factor = [1] * n
        T = 20
        best = [0] * T
        for t in range(T):
            for i in range(n):
                cost[i] += tires[i][0] * factor[i]
                factor[i] *= tires[i][1]
            best[t] = min(cost)

        dp = [1 << 30] * (1 + numLaps)
        dp[0] = 0
        for i in range(numLaps):
            for t in range(T):
                j = i + t + 1
                if j <= numLaps:
                    dp[j] = min(dp[j], dp[i] + best[t])
        return dp[numLaps] - changeTime