以前講過一個類似的問題流水做業調度問題,那一道題最開始用動態規劃,推到最後獲得了一個Johnson法則,變成了一個排序問題,有興趣的能夠看一下http://www.javashuo.com/article/p-xjlqyjke-ep.htmlhtml
本篇博客主要參考自https://blog.csdn.net/qq_40685275/article/details/80403976算法
給定n個做業的集合{J1,J2,…,Jn}。每一個做業必須先由機器1處理,而後由機器2處理。做業Ji須要機器j的處理時間爲tji。對於一個肯定的做業調度,設Fji是做業i在機器j上完成處理的時間。全部做業在機器2上完成處理的時間和稱爲該做業調度的完成時間和。批處理做業調度問題要求對於給定的n個做業,制定最佳做業調度方案,使其完成時間和達到最小。數組
例:設n=3,考慮如下實例:函數
看到這裏可能會對這些完成時間和是怎麼計算出來的會有疑問,這裏我拿123和312的方案來講明一下。spa
對於調度方案(1,2,3).net
做業1在機器1上完成的時間是2,在機器2上完成的時間是3設計
做業2在機器1上完成的時間是5,在機器2上完成的時間是63d
做業3在機器1上完成的時間是7,在機器2上完成的時間是10code
因此,做業調度的完成時間和= 3 + 6 + 10htm
這裏咱們能夠思考一下做業i在機器2上完成的時間應該怎麼去求?
做業i在機器1上完成的時間是連續的,因此是直接累加就能夠。但對於機器2就會產生兩種狀況,這兩種狀況其實就是上圖的兩種狀況,對於(1,2,3)的調度方案,在求做業2在機器2上完成的時間時,因爲做業2在機器1上尚未完成,這就須要先等待機器1處理完;而對於(3,1,2)的調度方案,在求做業2在機器2上完成的時間時,做業2在機器1早已完成,無需等待,直接在做業1被機器1處理以後就能接着被處理。
綜上,咱們能夠獲得以下表達式
if (F2[i-1] > F1[i]) F2[i] = F2[i-1] + t[2][i] else F2[i] = F1[i] + t[2][i]
類Flowshop的數據成員記錄解空間的結點信息,M輸入做業時間,bestf記錄當前最小完成時間和,數組bestx記錄相應的當前最佳做業調度。
數組x[i],bestx[i],二維數組m[j][i];
數組x記錄當前調度;
bestx記錄當前最優調度;
初始時,x[i]=i ; bestx[i]=∞; (i=0,1,......,n)
二維數組m記錄各做業分別在兩臺機器上的處理時間;
m[j][i]表示在第i臺機器上做業j的處理時間
變量f1,f2,cf,bestf;
f1記錄做業在第一臺機器上的完成時間;
f2記錄做業在第一臺機器上的完成時間;
cf記錄當前在第二臺機器上的完成時間和;
bestf記錄當前最優調度的完成時間和;
在遞歸函數Backtrack中,
當i>n時,算法搜索至葉子結點,獲得一個新的做業調度方案。此時算法適時更新當前最優值和相應的當前最佳調度。
當i<=n時,當前擴展結點在i層,以深度優先方式,遞歸的對相應子樹進行搜索,對不知足上界約束的結點,則剪去相應的子樹。
這裏注意一下該程序的輸入,要現將機器1對應全部做業的處理時間輸入,再輸入機器2的,對應上面的例子的數據就是 232113
#include <stdio.h> int x[100],bestx[100],m[100][100];//m[j][i]表示在第i臺機器上做業j的處理時間 //數組bestx記錄相應的當前最佳做業調度。 int f1=0,f2,cf=0,bestf=10000,n; //bestf記錄當前最小完成時間和 void swap(int *x,int t,int j) { int temp = x[t]; x[t] = x[j]; x[j] = temp; } void Backtrack(int t) { int tempf,j,i; if(t>n) //到達葉子結點,搜索到最底部 { for( i=1; i<=n; i++) { bestx[i]=x[i]; } bestf=cf; } else //非葉子結點 { for(j=t; j<=n; j++) { f1+=m[x[j]][1]; //記錄做業在第一臺機器上的完成處理時間 tempf=f2;//保存上一個做業在機器2的完成處理時間 f2=(f1>f2?f1:f2)+m[x[j]][2];//保存當前做業在機器2的完成時間 cf+=f2; //cf記錄當前在機器2上的完成時間和 if(cf<bestf) { swap(x,t,j); //交換兩個做業的位置 Backtrack(t+1); swap(x,t,j); } f1-=m[x[j]][1]; cf-=f2; f2=tempf; } } } int main() { int i,j; printf("請輸入做業數量\n"); scanf("%d",&n); printf("請輸入在各機器上的處理時間\n"); for(i=1; i<=2; i++) { for(j=1; j<=n; j++) { scanf("%d",&m[j][i]); } } for(i=1; i<=n; i++) { x[i]=i; //記錄當前調度 } Backtrack(1); printf("調度做業順序\n"); for(i=1; i<=n; i++) { printf("%d\t",bestx[i]); } printf("\n"); printf("處理時間:\n"); printf("%d\n",bestf); return 0; }
注意swap函數,交換兩個做業的位置至關於從新賦值了,因此該程序沒有對x[i]的賦值函數