📌  相关文章
📜  在两次连续迭代中不重复相同任务的情况下最小化总成本(1)

📅  最后修改于: 2023-12-03 15:23:28.734000             🧑  作者: Mango

在两次连续迭代中不重复相同任务的情况下最小化总成本

这是一个经典的优化问题,也被称为双倍加工问题。给定 $n$ 个任务和两个处理器,每个任务有一个处理时间 $t_i$,需要将任务分配给两个处理器处理。同一个处理器不能连续两次处理相同的任务。我们的目标是最小化两台处理器的总处理时间。

解决方案

我们需要使用动态规划来解决这个问题。我们将状态定义为 $(i,j,k)$,表示前 $i$ 个任务已经被分配,并且第一个处理器最后处理的任务是 $j$,第二个处理器最后处理的任务是 $k$。我们用 $f(i,j,k)$ 表示达到这个状态的最小总成本。

我们可以使用以下递归式来计算 $f(i,j,k)$:

$$ f(i,j,k) = \begin{cases} \infty & i = 1\text{ and }j = k \ 0 & i = 1\text{ and }j \neq k \ t_i + \min{ f(i-1,k,l) : l\in [1,n]\setminus{j,k} } & j \neq k \ \infty & \text{otherwise} \end{cases} $$

这个递归式的含义是,如果第一个处理器最后处理的任务和第二个处理器最后处理的任务是同一个任务,那么这种状态是无效的,我们将它的成本设为无穷大;如果前 $i$ 个任务已经被分配,但是第一台处理器最后处理的任务和第二台处理器最后处理的任务是不同的,那么我们需要将第 $i$ 个任务分配给其中一台处理器,并且计算前 $i-1$ 个任务的最小总成本;如果前 $i$ 个任务已经被分配,但是第一台处理器最后处理的任务和第二台处理器最后处理的任务是同一个任务,那么这种状态是无效的,我们将它的成本设为无穷大。

最终的答案是 $\min{f(n,j,k) : j,k\in [1,n]}$。

代码实现

以下是使用 Python 实现上述动态规划算法的代码:

def double_schedule(tasks):
  n = len(tasks)
  f = [[[float('inf')] * (n+1) for i in range(n+1)] for j in range(n+1)]
  for j in range(1, n+1):
    for k in range(1, n+1):
      if j != k:
        f[1][j][k] = tasks[0][j-1] + tasks[0][k-1]
  for i in range(2, n+1):
    for j in range(1, n+1):
      for k in range(1, n+1):
        if j != k:
          f[i][j][k] = tasks[i-1][j-1] + min(f[i-1][k][l] for l in range(1, n+1) if l != j and l != k)
  return min(f[n][j][k] for j in range(1, n+1) for k in range(1, n+1))

其中 tasks 是一个 $n\times n$ 的矩阵,第 $i$ 行第 $j$ 列表示第 $i$ 个任务在第 $j$ 台处理器上的处理时间。比如说,tasks[i][j] 表示第 $i$ 个任务在第 $j$ 台处理器上的处理时间。

# Example usage
tasks = [
  [1, 2, 3],
  [2, 1, 3],
  [3, 2, 1],
]
ans = double_schedule(tasks) # ans should be 6