LC每日一题|20240419 - 1883. 准时抵达会议现场的最小跳过休息次数

117 阅读3分钟

LC每日一题|20240419 - 1883. 准时抵达会议现场的最小跳过休息次数

给你一个整数 hoursBefore ,表示你要前往会议所剩下的可用小时数。要想成功抵达会议现场,你必须途经 n 条道路。道路的长度用一个长度为 n 的整数数组 dist 表示,其中 dist[i] 表示第 i 条道路的长度(单位:千米)。另给你一个整数 speed ,表示你在道路上前进的速度(单位:千米每小时)。

当你通过第 i 条路之后,就必须休息并等待,直到 下一个整数小时 才能开始继续通过下一条道路。注意:你不需要在通过最后一条道路后休息,因为那时你已经抵达会议现场。

  • 例如,如果你通过一条道路用去 1.4 小时,那你必须停下来等待,到 2 小时才可以继续通过下一条道路。如果通过一条道路恰好用去 2 小时,就无需等待,可以直接继续。

然而,为了能准时到达,你可以选择 跳过 一些路的休息时间,这意味着你不必等待下一个整数小时。注意,这意味着与不跳过任何休息时间相比,你可能在不同时刻到达接下来的道路。

  • 例如,假设通过第 1 条道路用去 1.4 小时,且通过第 2 条道路用去 0.6 小时。跳过第 1 条道路的休息时间意味着你将会在恰好 2 小时完成通过第 2 条道路,且你能够立即开始通过第 3 条道路。

返回准时抵达会议现场所需要的 最小跳过次数 ,如果 无法准时参会 ,返回 -1

提示:

  • n == dist.length
  • 1 <= n <= 1000
  • 1 <= dist[i] <= 10^5
  • 1 <= speed <= 10^6
  • 1 <= hoursBefore <= 10^7

题目等级:Hard

解题思路

首先,如果我们不休息时间都不够用的话,那么应该直接返回 -1

然后,我们可以定义一个二维dp数组dp[i][j],表示在跳过最多 i 次休息的情况下走完道路 j 所消耗的最短时间

对于其他 dp[i][j] ,易知存在以下转移:

  • dp[i - 1][j - 1] + dist[j] / speed: 完成 j - 1 时跳过休息
  • Math.ceil(dp[i][j - 1]) + + dist[j] / speed: 完成 j - 1 前已经休息过,此处不能跳过休息

显然这里我们应该求其较小值,然后找到满足 j == dist.size - 1 且时间小于等于 hoursBefore 的最小的 i 即可。

但是使用浮点数可能会带来精度问题,万一debug时踩坑会使我本不富裕的脑细胞雪上加霜。

所以这里我们就干脆不除以 speed 了,这样 dp[i][j] 就定义成了 该段时间内如果不休息能跑多远

AC代码

class Solution {
    fun minSkips(dist: IntArray, speed: Int, hoursBefore: Int): Int {
        val max = 1L * speed * hoursBefore
        if (dist.sum().toLong() > max) return -1   //所有休息时间都跳过,如果还是不够,直接返回-1
        val dp = Array<IntArray>(dist.size) { IntArray(dist.size) }
        dp[0][0] = dist[0]
        for (i in 1 until dp.size) {
            dp[i][0] = dist[0] 
            dp[0][i] = (dp[0][i - 1] + speed - 1) / speed * speed + dist[i]  
        }
        if (dp[0].last().toLong() <= max) return 0
        for (i in 1 until dp.size) {
            for (j in 1 until dp.size) {
                dp[i][j] = Math.min(
                    dp[i - 1][j - 1], 
                    (dp[i][j - 1] + speed - 1) / speed * speed
                ) + dist[j]
            }
            if (dp[i].last().toLong() <= max) return i
        }
        return -1
    }
}

时间复杂度:O(N^2)

空间复杂度:O(N^2)

N为dist的大小

碎碎念

我竟然AC了一道DP!!!!!!

图片.png