作业调度方案(codevs 1156)题解
【问题描述】
我们现在要利用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.