n个作业组成的作业集,可由m台相同机器加工处理。要求给出一种作业调度方案,使所给的n个作业在尽可能短的时间内由m台机器加工处理完成。作业不能拆分成更小的子作业;每个作业均可在任何一台机器上加工处理。
这个问题是NP完全问题,还没有有效的解法(求最优解),但是可以用贪心选择策略设计出较好的近似算法(求次优解)。当n<=m时,只要将作业时间区间分配给作业即可;当n>m时,首先将n个作业从大到小排序,然后依此顺序将作业分配给空闲的处理机。也就是说从剩下的作业中,选择需要处理时间最长的,然后依次选择处理时间次长的,直到所有的作业全部处理完毕,或者机器不能再处理其他作业为止。如果我们每次是将需要处理时间最短的作业分配给空闲的机器,那么可能就会出现其它所有作业都处理完了只剩所需时间最长的作业在处理的情况,这样势必效率较低。在下面的代码中没有讨论n和m的大小关系,把这两种情况合二为一了。
具体实现代码如下所示:
/**
*@Title: MultiMachineSchedule.java
*@Package greedyalgorithm
*@Description: TODO
*@author peidong
*@date 2017-5-17 上午9:42:01
*@version V1.0
*/
packagegreedyalgorithm;
importjava.util.ArrayList;
importjava.util.Collections;
importjava.util.LinkedList;
importjava.util.List;
/**
* @ClassName: MultiMachineSchedule
* @Description: 多机调度问题
* @date 2017-5-17 上午9:42:01
*
*/
publicclass MultiMachineSchedule {
/**
*
* @ClassName: TaskNode
* @Description: 任务结点
* @date 2017-5-17 上午9:58:10
*
*/
public static class TaskNode implementsComparable{
int id; //作业标号
int time; //作业时间
/**
*
* Title:
* Description:构造函数
* @param id
* @param time
*/
public TaskNode(int id, int time){
this.id = id;
this.time = time;
}
/*
* Title:compareTo
* Description: 按时间长短从大到小排列作业
* @param o
* @return
* @seejava.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Object o) {
// TODO Auto-generatedmethod stub
int times =((TaskNode)o).time;
if(time > times)
return -1;
if(time == times)
return 0;
return 1;
}
}
/**
*
* @ClassName: MachineNode
* @Description: 机器结点
* @date 2017-5-17 上午10:02:30
*
*/
public static class MachineNodeimplements Comparable{
int id;//机器标号
int avail; //机器空闲时间
/**
*
* Title:
* Description:构造函数
* @param id
* @param avail
*/
public MachineNode(int id, intavail){
this.id = id;
this.avail = avail;
}
/*
* Title:compareTo
* Description:升序排序,LinkedList的first为最小的
* @param o
* @return
* @seejava.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Object o) {
// TODO Auto-generatedmethod stub
int xs =((MachineNode)o).avail;
if(avail < xs)
return -1;
if(avail == xs)
return 0;
return 1;
}
}
public static int greedy(int[] a, int m){
int n = a.length - 1; ////a的下标从1开始,所以n(作业的数目)=a.length-1
int sum = 0;
//如果作业数量小于机器数量
if(n <= m){
for(int i = 0; i < n;i++){
sum+= a[i+1];
System.out.println("为每个作业分别分配一台机器");
return sum;
}
}
List
for(int i = 0; i < n; i++){//将所有的作业存入List中,保存id和时间
TaskNode tn = newTaskNode(i+1, a[i+1]);
d.add(tn); //入队
}
Collections.sort(d); //对作业进行排序
LinkedList
for(int i = 1; i < m; i++){ //将所有的机器存入链表中
MachineNode mn = newMachineNode(i,0); //初始化时,每台机器的空闲时间为0
h.add(mn); //入队
}
int len = h.size();
for(int i = 0; i < n; i++){
Collections.sort(h); //对机器进行排序
MachineNode temp =h.peek();
System.out.println("将机器"+temp.id+"从"+temp.avail+"到"+(temp.avail+d.get(i).time)+"的时间段分配给作业"+d.get(i).id);
temp.avail+=d.get(i).time;
sum = temp.avail;
}
return sum;
}
/**
*@Title: main
*@Description: TODO
*@param args
*@return void
*@throws
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a={0,2,14,4,16,6,5,3};
int m=5;
int sum=greedy(a,m);
System.out.println("总时间为:"+sum);
}
}