返回

LeetCode 1494. 并行课程II:攻克难题的最佳技巧

后端

LeetCode 1494:并行课程 II

背景

在 LeetCode 1494. 并行课程 II 中,你有一组课程,每个课程都有其先修课程。你的目标是安排这些课程的执行顺序,以便所有课程都能在最短时间内完成。此外,你可以使用多台机器并行执行课程。

解决方案:状态压缩动态规划

解决这个问题的一种有效方法是状态压缩动态规划。让我们将问题分解为子问题,并从那里逐步构建最优解。

状态定义

我们定义一个状态 dp[mask][i] ,其中:

  • mask 是一个二进制掩码,表示已完成课程的集合。
  • i 是当前使用的机器编号。

dp[mask][i] 表示在已完成课程为 mask 的情况下,使用第 i 台机器执行剩余课程的最小执行时间。

状态转移方程

对于每个状态 dp[mask][i] ,我们可以枚举所有可能执行的课程 j 来更新它的值:

dp[mask][i] = min(dp[mask][i], dp[mask ^ (1 << j)][i - 1] + time[j])

其中:

  • mask ^ (1 << j) 表示将课程 j 添加到已完成课程的掩码。
  • i - 1 表示使用上一台机器执行课程 j
  • time[j] 表示执行课程 j 所需的时间。

算法流程

  1. 初始化:将 dp[0][0] 设置为 0,将其他状态值设为无穷大。
  2. 对于每个课程 j
    • 枚举所有可能的执行顺序:
      • 如果课程 j 可以执行(没有先修课程或先修课程已完成),则计算 dp[mask][i] 的值。
      • 更新 dp[mask][i] 的值为最小的执行时间。
  3. 返回 dp[(1 << n) - 1][m - 1] ,其中 n 是课程数,m 是机器数。

代码示例(Python)

import math

def min_time_to_complete_courses(prerequisites, num_courses, num_machines):
    dp = [[math.inf for _ in range(num_machines)] for _ in range(1 << num_courses)]
    dp[0][0] = 0

    graph = [[] for _ in range(num_courses)]
    for course, prereq in prerequisites:
        graph[prereq].append(course)

    for mask in range(1 << num_courses):
        for i in range(num_machines):
            for course in range(num_courses):
                if (mask & (1 << course)) == 0:
                    time_to_complete = 0
                    for prereq in graph[course]:
                        time_to_complete = max(time_to_complete, dp[mask ^ (1 << course)][i - 1])
                    time_to_complete += 1

                    dp[mask][i] = min(dp[mask][i], time_to_complete)

    return dp[(1 << num_courses) - 1][num_machines - 1]

结论

通过使用状态压缩动态规划,我们可以高效地解决 LeetCode 1494. 并行课程 II。这种方法将问题分解为一系列子问题,并通过构建子问题的最优解来找到整体最优解。

常见问题解答

  1. 为什么使用状态压缩动态规划?
    状态压缩动态规划允许我们有效地存储子问题的解决方案,从而避免重复计算。

  2. 如何确定课程的执行顺序?
    执行顺序取决于状态转移方程计算的最小执行时间。

  3. 如何处理没有先修课程的课程?
    没有先修课程的课程可以立即执行,因此它们的掩码中只有一位为 1。

  4. 机器之间的执行时间是否相同?
    算法假设所有机器的执行时间相同。

  5. 这个算法的时间复杂度是多少?
    算法的时间复杂度为 O(2^n * m * n) ,其中 n 是课程数,m 是机器数。