N个做业{1,2,………,n}要在由两台机器M1和M2组成的流水线上完成加工。每一个做业加工的顺序都是先在M1上加工,而后在M2上加工。M1和M2加工做业i所需的时间分别为ai和bi,1≤i≤n。流水做业高度问题要求肯定这n个做业的最优加工顺序,使得从第一个做业在机器M1上开始加工,到最后一个做业在机器M2上加工完成所需的时间最少。ios
直观上,一个最优调度应使机器M1没有空闲时间,且机器M2的空闲时间最少。在通常状况下,机器M2上会有机器空闲和做业积压2种状况。算法
最优调度应该是:函数
1. 使M1上的加工是无间断的。即M1上的加工时间是全部ai之和,但M2上不必定是bi之和。spa
2. 使做业在两台机器上的加工次序是彻底相同的。3d
则得结论:仅需考虑在两台机上加工次序彻底相同的调度。code
设所有做业的集合为N={1,2,…,n}。S是N的做业子集。在通常状况下,机器M1开始加工S中做业时,机器M2还在加工其余做业,要等时间t后才可利用。将这种状况下完成S中做业所需的最短期记为T(S,t)。流水做业调度问题的最优值为T(N,0)。 blog
这个T(S,t)该如何理解?举个例子就好搞了(用ipad pencil写的...没贴类纸膜,太滑,凑合看吧)ip
T(N,0)=min{ai + T(N-{i}, bi)}, i∈N。ci
ai:选一个做业i先加工,在M1的加工时间。it
T(N-{i},bi}:剩下的做业要等bi时间后才能在M2上加工。注意这里函数的定义,由于一开始工做i是随机取的,M1加工完了ai以后,要开始加工bi了,这里M1是空闲的能够开始加工剩下的N-i个做业了,但此时M2开始加工bi,因此要等bi时间以后才能从新利用,对应到上面函数T(s,t)的定义的话,这里就应该表示成T(N-{i},bi), 因此最优解可表示为T(N,0)=min{ai + T(N-{i}, bi)}, i∈N,即咱们要枚举全部的工做i,使这个式子取到最小值。
继续分析T(S,t)可得:
T(S,t)={ai + T(S-{i}, bi+max{t-ai,0})}, i∈S
其中:T(S-{i}, bi+max{t-ai,0}):剩下的做业等bi+max{t-ai,0}才能在M2加工,至于这里是怎么推导出来的呢?见下面推导:
这段证实不是很好理解,简单来讲就是要证实问题的最优解包含子问题的最优解就好了,那么这里的证实思路是先假设一个最优调度,对于他的子调度T’,由于T(S,t)被定义为是完成S中做业所需的最短期记为T(S,t),因此有T’>=T(S, bπ1),那么若是这个子调度这里不是最优解的话即T’>T(S, bπ1),会得出aπ1+T’ > aπ1+T(S, bπ1)即原来假设的最优调度不符和最优调度的标准,矛盾,从而推出 T’是必定等于T(S, bπ1),即这个子调度也是最优调度。
问题是:虽然知足最优子结构性质,也在必定程度知足子问题重叠性质。N的每一个非空子集都计算一次,共2n-1次,指数级的。
为了解决这个问题引入Johnson不等式
推导公式的最后两步,做用是提出bi和aj,而后直接max三元素
假设有下列的7个做业:
#include <iostream> #include <algorithm> using namespace std; class JOB { public: int key,index; bool job; }; bool cmp(JOB a,JOB b) { return a.key<b.key; } int func(int n,int a[],int b[],int c[]) { int i,j,k; JOB *d =new JOB[n]; for(i=0;i<n;i++) { if(a[i]<b[i]) { d[i].job =true; d[i].key =a[i]; } else { d[i].job=false; d[i].key=b[i]; } d[i].index=i; } sort(d,n+d,cmp); j=0,k=n-1; for(i=0;i<n;i++) { if(d[i].job ==true) c[j++]=d[i].index; else c[k--]=d[i].index; } j=a[c[0]]; k=j+b[c[0]]; for(i=1;i<n;i++) { j=j+a[c[i]]; k= j<k ? k+b[c[i]] : j+b[c[i]] ; } delete d; return k; } int main() { int i,n,m,a[100],b[100],c[100]; cin>>n; while(n--) { cin>>m; for(i=0;i<m;i++) { cin>>a[i]; cin>>b[i]; } cout<<func(m,a,b,c)<<endl; } return 0; } /* 1 7 5 2 3 4 6 7 4 2 8 9 9 7 6 3 */
结果:43