M台机器处理n个任务 java_贪心算法实例(三):多机调度问题

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 d = newArrayList();  //保存所有的作业

for(int i = 0; i < n; i++){//将所有的作业存入List中,保存id和时间

TaskNode tn = newTaskNode(i+1,  a[i+1]);

d.add(tn); //入队

}

Collections.sort(d); //对作业进行排序

LinkedList h =new LinkedList(); //h保存所有的机器

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);

}

}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算法思想:贪心算法 + 最小堆 1. 首先将 n 个作业按照所需处理时间 t 从大到小排序 2. 创建一个大小为 m 的最小堆,将前 m 个作业加入堆中 3. 对于剩余的作业,每次从堆中取出处理时间最短的作业,将其分配到该作业所需处理时间最短的机器上,并更新该机器处理时间 4. 将新的作业加入堆中,重复步骤 3 直到所有作业都被处理完毕 具体伪码: ``` 1. 将作业按照处理时间从大到小排序 2. 创建大小为 m 的最小堆 heap 3. for i in range(m): 将作业 i 分配到第 i 机器上,并更新该机器处理时间 将作业 i 的处理时间加入堆 heap 中 4. for i in range(m, n): 取出堆顶元素 job,将其分配到处理时间最短的机器上,并更新该机器处理时间 将 job 的处理时间加入堆 heap 中 5. 返回最后一机器处理时间作为总时间 ``` 正确性证明: - 对于第一组 m 个作业,我们将它们分配到 m 机器上,每机器处理时间为该作业所需处理时间。因此,这 m 个作业的总时间为 m 机器处理时间最长的那机器处理时间。 - 对于第二组作业,我们每次从堆中取出处理时间最短的作业,并将其分配到处理时间最短的机器上。因此,第二组作业的总时间一定不会超过第一组作业的总时间,即不会超过 m 机器处理时间最长的那机器处理时间。 - 由于我们在每次分配作业时都选择了处理时间最短的机器,因此在最坏情况下,每机器处理时间都不会超过总时间的两倍。因此,我们得到的调度方案一定是最优的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值