引入:何为流水线问题
有\(n\)个任务,对于每个任务有\(m\)道工序,每个任务的\(m\)道工序必须在不同的m台机器上依次完成才算把这个任务完成,在前\(i-1\)道工序完成后才能去完成第\(i\)道工序。对于每一个任务的每一道工序在每一台机器上需要的时间都是不同的,求最短完成所有任务的时间,也就是最后一个任务的最后一道工序的完成时间。
流水线问题分为可抢先调度和非抢先调度。在现实生活中,某些时候某个任务会因为突发情况而获得较高的优先级,那么我们就会停下正在做的任务,直接开始这个优先级较高的问题,这就是抢先调度。
由于抢先调度和多流水线的情况比较复杂,所以我们在比赛中很难碰见碰见了就意味着你有更多的时间去写剩下的两道题多吼哇,所以我们只研究非抢先调度的双流水线调度问题。
双流水线问题所具有的适合动态规划的性质
假设第一个机器为\(M1\),第二个机器为\(M2\),第\(i\)个任务在第一个机器上所需的时间是\(a_i\),在第二个机器上所需的时间是\(b_i\)。肯定存在某个最优的策略使得\(M2\)接受的任务的先后顺序和\(M1\)接受的任务顺序一模一样。
在最优策略下,\(M1\)肯定是没有空闲时间的,而\(M2\)只有两种状态,一种是空闲的,一种是任务积压着。不管对于那种状态,\(M2\)接受任务的顺序跟\(M1\)保持一致显然是最优的,因为这样会使\(M2\)的空闲时间最少,也就会使最后一个任务的第二道工序更快完成。
我们令\(T\)(\(s\),\(t\))表示当\(M1\)开始处理任务集合\(s\)时,\(M2\)还需要时间\(t\)才能投入使用,最后完成任务集合\(s\)的最快时间。那么对于非抢先调度问题的答案就是\(T\)(\(N\),\(0\))。
假设最优策略选择第\(i\)个任务最先做,显然答案就是\(a_i\)+\(T\)(\(N-\){\(i\)},\(b_i\))。
再推广一点,对于每个\(T\)(\(s\),\(t\)),都满足\(T\)(\(s\),\(t\))=\(min\){\(a_i\)+\(T\)(\(s-\){\(i\)},\(b_i+max\)(\(t-a_i\),0))}。意思就是在\(M2\)还需要\(t\)时间才能投入使用来执行任务集合\(s\)内的任务时,\(M1\)优先执行任务集合\(s\)里的任务,并且选择第\(i\)号任务为集合\(s\)里第一个被执行的任务,所以在执行\(a_i\)时,\(M2\)的等待时间\(t\)自然也会减少,但是就算\(M2\)上的任务清空了也只能等着\(M1\)这边的任务第一道工序加工完才能再次工作,所以后面的等待时间是\(b_i+max\)(\(t-a_i\),\(0\)),而剩下的任务集合就是\(s-\){\(i\)}。
显然这个动态规划是正确的,但是由于任务的数量过多和任务耗时较长,这个方法并不能很好的解决双流水线非抢先调度问题。
算法进化:\(Jhonson\)登场
假设在最优策略下,对于任务集合\(s\),在\(T\)(\(s\),\(t\))的情况下,第一个在\(M1\)上执行的是\(i\)号任务,第二个是\(j\)号。那么\(T\)(\(s\),\(t\))就可以转化成\(a_i+T\)(\(s-\){\(i\)},\(b_i+max\) (\(t-a_i\),\(0\))),再转化成\(a_i+a_j+T\)(\(s-\){i,j},\(t_{ij}\))。
\(t_{ij}=b_j+max\)(\(b_i+max\)(\(t-a_i\),\(0\))\(-a_j\),\(0\)))
在最外层的\(max\)里提出一个\(b_i-a_j\):
\(t_{ij}=b_j+b_i-a_j+max\)(\(max\)(\(t-a_i\),\(0\)),\(a_j-b_i\)))
\(t_{ij}=b_j+b_i-a_j+max\)(\(t-a_i\),\(0\),\(a_j-b_i\))
再提一个\(-a_i\)出来:
\(t_{ij}=b_j+b_i-a_i-a_j+max\)(\(t\),\(a_i\),\(a_i+a_j-b_i\))
那么在最优策略下,先\(i\)后\(j\)和先\(j\)后\(i\)的区别就只能在那个\(max\)里体现出来了。而\(max\)也刚好影响着\(M2\)的空闲时间,也就是最后答案。那么我们把先\(i\)后\(j\)和先\(j\)后\(i\)的\(max\)分别写出来,他们满足下面这个关系:
\[max(t,a_i,a_i+a_j-b_i)\leqslant max(t,a_j,a_i+a_j-b_j)\]
先假设\(t\)为一个极小值,把它的影响抹去,我们化简一下:
\[max(a_i,a_i+a_j-b_i)\leqslant max(a_j,a_i+a_j-b_j)\]
\[a_i+a_j+max(-a_j,-b_i)\leqslant a_i+a_j+max(-a_i,-b_j)\]
见证奇迹的时刻到了!!我们再次化简!
\[max(-a_j,-b_i)\leqslant max(-a_i,-b_j)\]
等价于:
\[min(a_i,b_j)\leqslant min(a_j,b_i)\]
可是,也许最开始\(max\)里的\(t\)消失得不明不白,这个时候我们反着推回去,只需要满足\(min(a_i,b_j)\leqslant min(a_j,b_i)\)的话,对于任意\(t\)也就必然满足\(max(t,a_i,a_i+a_j-b_i)\leqslant max(t,a_j,a_i+a_j-b_j)\)了。所以只需要满足\(min(a_i,b_j)\leqslant min(a_j,b_i)\)就是最优的调度决策。
于是乎,传说中的\(Jhonson\)表达式就出炉了。对于任何双流水线非抢先调度问题的最优解,任意相邻的\(i,j\)都满足\(Jhonson\)表达式,因为任意相邻的\(i,j\)都有这个比较法则和小于号的传递性,所以任意不相邻的\(i,j(i