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