1.问题描述
给定n个作业的集合{J1, J2, …, Jn}。每一个作业Ji都有两项任务需要分别在2台机器上完成。每个作业必须先由机器1处理,然后由机器2处理。
三个作业的调度方案对应三个作业的全排列。三个作业的6种可能的调度方案是1, 2, 3;1, 3, 2;2, 1, 3;2, 3, 1;3, 2, 1;3, 1, 2。批处理作业调度问题要求制定最佳作业调度方案,使其完成时间和达到最小。
Java实现
public class JobSched {
int n;//作业数
int f1;//机器1完成处理时间
int f;//完成时间和
int bestf;//当前最优值
int[][] m;//各作业所需的处理时间
int []x;//当前作业调度
int[] bestx;//当前最优作业调度
int[] f2;//机器2完成处理时间
//构造函数
public JobSched(int n, int[][] m){
this.n=n;
this.m=m;
f1=0;
f=0;
bestf=9999;//给定初始值
//创建空数组
bestx=new int[n+1];
x=new int[n+1];
//初始化,x[i]为原始排序
for(int i=1;i<=n;i++){
x[i]=i;
}
f2=new int[n+1];
}
//交换作业顺序 完成全排列
private void swap(int[] x,int i,int j){
int temp=x[i];
x[i]=x[j];
x[j]=temp;
}
//参数i表示树的第几层,从1开始
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++){
//作业x[j]在第一台机器的时间
f1+=m[x[j]][1];
//f2[i]等于max(f2[i-1],f1)+作业x[j]在第2台机器的时间
f2[i]=((f2[i-1]>f1)?f2[i-1]:f1)+m[x[j]][2];
//完成时间和
f+=f2[i];
//完成时间和小于最优值
if(f<bestf){
//交换两个作业的位置,把选择出的原来在x[j]位置上的任务调到当前执行的位置x[i]
swap(x,i,j);
backtrack(i+1);//深度搜索解空间树,进入下一层
swap(x,i,j);//进行回溯,还原
}
//回溯需要还原各个值
f1-=m[x[j]][1];
f-=f2[i];
}
}
}
public static void main(String[] args) {
int n=3;
//m的下标从1开始,因此第一行的0和每一行第一列的0无用
int[][] m={{0,0,0},{0,2,1},{0,3,1},{0,2,3}};
JobSched jobSched=new JobSched(n,m);
jobSched.backtrack(1);
System.out.println("最优批处理作业调度顺序为:");
for(int i=1;i<=n;i++)
System.out.print(jobSched.bestx[i]+" ");
System.out.println();
System.out.println("最优调度所需的最短时间为:"+jobSched.bestf);
}
}
JavaScript实现
(function(){
// 用户输入的
let n=3;//作业数量
let m=[[0,0,0],[0,2,1],[0,3,1],[0,2,3]];//作业调度
let f1=0;//机器1完成的时间
let f2=[0,0,0,0];//机器2完成的时间
let x=new Array(n+1);//作业调度的顺序
for(let i=0;i<=n;i++){
x[i]=i;
}
let f=0;//调度总和
// 求的
let bestX=new Array(n+1);//最优的调度顺序
let bestF=9999;//最优调度
// 交换调度函数
function swap(x,i,j){
let temp=x[i];
x[i]=x[j];
x[j]=temp;
}
function backTrack(t){
//到达叶子结点
if(t>n){
for(let j=1;j<=n;j++)
//更新最优调度序列
bestX[j]=x[j];
//更新最优目标值
bestF=f;
}else{//非叶子结点
for(let j=t;j<=n;j++){
//作业x[j]在第一台机器的时间
f1+=m[x[j]][1];
//f2[i]等于max(f2[i-1],f1)+作业x[j]在第2台机器的时间
f2[t]=(f2[t-1]>f1?f2[t-1]:f1)+m[x[j]][2];
//完成时间和
f+=f2[t];
if(f<bestF){
swap(x,t,j);
backTrack(t+1);
// 回溯还原调度顺序
swap(x,t,j);
}
// 回溯还原值
f-=f2[t];
f1-=m[x[j]][1];
}
}
}
backTrack(1);
// 打印
let str='';
for(let j=1;j<=n;j++)
str+=bestX[j]+", "
console.log("最优的调度顺序为"+str)
console.log("最优的调度时间为"+bestF);
})();