问题描述:
给定n个作业的集合{J1,J2,…,Jn}。每个作业必须先由机器1处理,然后由机器2处理。作业Ji需要机器j的处理时间为tji。对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时间。所有作业在机器2上完成处理的时间和称为该作业调度的完成时间和。
批处理作业调度问题要求对于给定的n个作业,制定最佳作业调度方案,使其完成时间和达到最小。
例:设n=3,考虑以下实例:
这3个作业的6种可能的调度方案是1,2,3;1,3,2;2,1,3;2,3,1;3,1,2;3,2,1;它们所相应的完成 时间和分别是19,18,20,21,19,19。易见,最佳调度方案是1,3,2,其完成时间和为18。
源代码:
public class 批处理作业回溯法 {
static class Flowshop{
int M[][];
int x[];
int f2[];
int f1;
int f;
int bestx[];
int bestf;
int n;
Flowshop(int M[][],int x[],int f2[],int bestx[],int f1,int f,int bestf,int n){
this.M=M;
this.x=x;
this.bestx=bestx;
this.f2=f2;
this.f1=f1;
this.bestf=bestf;
this.f=f;
this.n=n;
}
private void backtrack(int i) {
if(i>n) {//至叶节点
for(int j=1;j<=n;j++)
bestx[j]=x[j];
bestf=f;
}
else
for(int j=i;j<=n;j++) {
f1+=M[x[j]][1];
f2[i]=((f2[i-1]>f1)?f2[i-1]:f1)+M[x[j]][2];//计算得出f2[i]
f+=f2[i];
if(f<bestf) {//若f>=bestf,则不必继续递归进行下一节点
swap(i,j,x);//交换x[i]和x[j]
backtrack(i+1);
swap(i,j,x);//交换x[i]和x[j]
}
f1-=M[x[j]][1];
f-=f2[i];
}
}
//交换方法
private static void swap(int i,int j,int x[]) {
int temp=x[j];
x[j]=x[i];
x[i]=temp;
}
//计算,打印并返回各作业在机器1上完成时间
private int[] time1(int bestx[],int M[][]) {
int machine1[]=new int[bestx.length];
for(int i=1;i<M.length;i++) {
int time=0;
for(int j=i;j>0;j--)
time+=M[bestx[j]][1];
machine1[i]=time;
System.out.println("作业"+bestx[i]+"在机器1上完成的时间为:"+time);
}
return machine1;
}
//计算,打印并返回各作业在机器2上完成时间
private static int[] time2(int bestx[],int M[][],int time1[]) {
int machine2[]=new int[bestx.length];
int time=0;int ii=0; //ii为对原表的引用
for(int i=1;i<M.length;i++) {//i为第i个进行的工作
ii=bestx[i];
if(i==1) time+=time1[1];
if(i==bestx.length-1) {
machine2[i]=time+M[ii][2];
System.out.println("作业"+bestx[i]+"在机器2上完成的时间为:"+machine2[i]);
return machine2;
}
machine2[i]=time+M[ii][2];
if(machine2[i]<time1[i+1])//下一个作业等待判断及time预置
time=time1[i+1];
else
time+=M[ii][2];
System.out.println("作业"+bestx[i]+"在机器2上完成的时间为:"+machine2[i]);
}
return machine2;
}
}//Flowshop至此结束
public static void main(String args[]) {//主函数
int ub=1000;
// M记录各作业分别在机器上的运作耗时 1 2
int M[][]=new int[][]{ /*0*/ {0, 0 , 0 },
/*1*/ {0, 2 , 3 },
/*2*/ {0, 3 , 1 },
/*3*/ {0, 2 , 1 },
};
int n=M.length-1;//作业个数
int x[]=new int [n+1];//当前作业调度
int f2[]=new int [n+1];//机器2完成处理的时间
int f1=0; //机器1完成处理的时间
int f=0; //完成处理的时间和
int bestx[]=new int[n+1];//当前最优作业调度
int bestf=ub; //当前最优值
//初始化作业调度顺序
for(int i=0;i<=n;i++) x[i]=i;
//构造问题并展示数据
Flowshop problem=new Flowshop(M,x, f2, bestx, f1, f, bestf, n);
System.out.println("作业信息如下");
System.out.println("机器 一 二");
for(int i=1;i<M.length;i++) {
System.out.print(""+i+"号: ");
for(int j=1;j<M[1].length;j++) {
System.out.print(M[i][j]+" ");
}
System.out.println();
}
System.out.println();
//调用backtrack解决问题
problem.backtrack(1);
//展示最优调度
System.out.println("最优安排如下:");
for(int i=1;i<bestx.length;i++)
System.out.print(bestx[i]+" ");
System.out.println('\n');
//打印各作业在机器12上完成时间
int machine1[]=problem.time1(bestx,M);
System.out.println();
int machine2[]=problem.time2(bestx,M,machine1);
System.out.println('\n'+"共用时:"+problem.bestf);
}
}