1.问题模型:
n个作业{0,1,2,…,n}在2台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,后在M2上加工。在两台机器上加工的时间分别为ai和bi,确定这n个作业的加工顺序,使得从第一台作业开始加工,到最后一个作业完成加工所需要的时间最少。
2.流水作业调度问题的Johnson算法:
(1)令N1={i|ai<bi},N2={i|ai>=bi};
(2)将N1中作业依ai的非减序排序;N2中作业依bi的非增序排序;
(3)N1中作业接N2中作业构成满足Johnson法则的最优调度。
3.思路
(1) a[i]和b[i]分别存储第i个作业在M1、M2上的加工时间,c[i]存储作业的最优加工顺序;
(2) 将a[i],b[i]中较小的那个放到数组d的key值并通过Arrays.sort()方法按key值进行排序;
(3)d[i].job为true的属于N1保存在c[i]前面,d[i].job为false的属于N2保存在c[i]后面,以此得出最优加工顺序和最短加工时间。
4.代码
package flowshop;
public class Johnson {
private static class Element implements Comparable<Object>{
int key;
int index;
boolean job;
public Element(int kk,int ii,boolean jj){
key = kk;
index = ii;
job = jj;
}
public int compareTo(Object x) {
int xkey =((Element)x).key;
if(key<xkey) return -1;
if(key==xkey) return 0;
return 1;
}
}
public static int flowShop(int[] a,int[] b,int[] c){
int n = a.length;
Element[] d = new Element[n];
for(int i=0;i<n;i++){
int key=a[i]>b[i]? b[i]:a[i];
boolean job = a[i]<=b[i];
d[i] = new Element(key,i,job);
}
java.util.Arrays.sort(d);
int j=0,k=n-1;
for(int i=0;i<n;i++){
if(d[i].job)
c[j++]=d[i].index;
else
c[k--]=d[i].index;
}
j=a[c[0]];
k=j+b[c[0]];
for(int i=1;i<n;i++){
j+=a[c[i]];
k=j<k?k+b[c[i]]:j+b[c[i]];
}
System.out.println("作业的最优加工顺序为(编号从0开始):");
for(int i=0;i<c.length;i++){
System.out.print(c[i]+" ");
}
System.out.println();
return k;
}
public static void main(String[] args) {
int[] a=new int[6];
int[] b=new int[6];
int[] c=new int[6];
for(int i=0;i<a.length;i++){
a[i]=(int) (Math.random()*10+1);
b[i]=(int) (Math.random()*10+1);
System.out.println("第"+i+"个作业在M1,M2上的加工时间为:"+a[i]+" "+b[i]);
}
int k = flowShop(a, b, c);
System.out.println("完成作业的最短时间为:"+k);
}
}
5.结果
