我們現在要利用m臺機器加工n個工件,每個工件都有m道工序,每道工序都在不同的指定的機器上完成。每個工件的每道工序都有指定的加工時間。
每個工件的每個工序稱爲一個操作,我們用記號j-k表示一個操作,其中j爲1到n中的某個數字,爲工件號;k爲1到m中的某個數字,爲工序號,例如2-4表示第2個工件第4道工序的這個操作。在本題中,我們還給定對於各操作的一個安排順序。
例如,當n=3,m=2時,“1-1,1-2,2-1,3-1,3-2,2-2”就是一個給定的安排順序,即先安排第1個工件的第1個工序,再安排第1個工件的第2個工序,然後再安排第2個工件的第1個工序,等等。
一方面,每個操作的安排都要滿足以下的兩個約束條件。
(1) 對同一個工件,每道工序必須在它前面的工序完成後才能開始;
(2) 同一時刻每一臺機器至多隻能加工一個工件。
另一方面,在安排後面的操作時,不能改動前面已安排的操作的工作狀態。
由於同一工件都是按工序的順序安排的,因此,只按原順序給出工件號,仍可得到同樣的安排順序,於是,在輸入數據中,我們將這個安排順序簡寫爲“1 1 2 3 3 2”。
還要注意,“安排順序”只要求按照給定的順序安排每個操作。不一定是各機器上的實際操作順序。在具體實施時,有可能排在後面的某個操作比前面的某個操作先完成。
例如,取n=3,m=2,已知數據如下:
工件號 機器號/加工時間
工序1 工序2
1 1/3 2/2
2 1/2 2/5
3 2/2 1/4
則對於安排順序“1 1 2 3 3 2”,下圖中的兩個實施方案都是正確的。但所需要的總時間分別是10與12。
當一個操作插入到某臺機器的某個空檔時(機器上最後的尚未安排操作的部分也可以看作一個空檔),可以靠前插入,也可以靠後或居中插入。爲了使問題簡單一些,我們約定:在保證約束條件(1)(2)的條件下,儘量靠前插入。並且,我們還約定,如果有多個空檔可以插入,就在保證約束條件(1)(2)的條件下,插入到最前面的一個空檔。於是,在這些約定下,上例中的方案一是正確的,而方案二是不正確的。顯然,在這些約定下,對於給定的安排順序,符合該安排順序的實施方案是唯一的,請你計算出該方案完成全部任務所需的總時間。
【樣例輸入】
2 3
1 1 2 3 3 2
1 2
1 2
2 1
3 2
2 5
2 4
【樣例輸出】
10
【解題思路】
本題爲NOIP2006提高組第三題,本人認爲之所以放在第三題是因爲該題考察的語文閱讀的能力實在是強悍至極,然而,真正的算法只是純模擬……它說了什麼,你就怎麼做,就行了。於是乎,我們按照安排的順序一個一個地安排在什麼時候放入什麼機器,有足夠的時間間隙就可以放入(奇怪,我爲什麼要加粗呢……),我們用一個數組來模擬m臺機器的工作流程即可,最後計算一下最晚完成工作的機器是在什麼時候完成的即可。
【代碼實現】
1 label 1; 2 var f:array[0..101,0..10000] of boolean; 3 a:array[0..1001] of longint; 4 i,j,n,m,k,ans,sum:longint; 5 b:array[0..101] of longint; 6 qian:array[0..101] of longint; 7 xh,sj:array[0..101,0..101] of longint; 8 begin 9 readln(m,n); 10 fillchar(f,sizeof(f),true); 11 for i:=1 to n*m do 12 read(a[i]); 13 for i:=1 to n do 14 for j:=1 to m do 15 read(xh[i,j]); 16 for i:=1 to n do 17 for j:=1 to m do 18 begin 19 read(sj[i,j]); 20 sum:=sum+sj[i,j]; 21 end; 22 for i:=1 to n*m do 23 begin 24 inc(b[a[i]]); 25 k:=qian[a[i]]+1; 26 1: while not f[xh[a[i],b[a[i]]],k] do 27 inc(k); 28 for j:=k to k+sj[a[i],b[a[i]]]-1 do 29 if not f[xh[a[i],b[a[i]]],j] then 30 break; 31 if (j=k+sj[a[i],b[a[i]]]-1)and(f[xh[a[i],b[a[i]]],j]) then 32 for j:=k to k+sj[a[i],b[a[i]]]-1 do 33 f[xh[a[i],b[a[i]]],j]:=false 34 else 35 begin 36 k:=j; 37 goto 1; 38 end; 39 qian[a[i]]:=k+sj[a[i],b[a[i]]]-1; 40 while not f[xh[a[i],b[a[i]]],k] do 41 inc(k); 42 end; 43 for i:=1 to m do 44 for j:=1 to sum do 45 if (not f[i,j])and(j>ans) then 46 ans:=j; 47 writeln(ans); 48 end.