import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
/**
* 贪心算法_作业调度问题
* @author Matt
*/
public class JobAssignment {
/**
* 定义一个类表示作业节点
* @author Matt
*/
public static class JobNode implements Comparable {
int id, time; // 作业的属性:序号、所需时间
JobNode(int i, int tt) { // 构造器,传递作业的序号和时间
id = i;
time = tt;
}
@Override
public int compareTo(Object x) { // 从大到小排序
// 获取被比较作业的所需时间
int xt = ((JobNode) x).time;
if (time > xt) return -1; // -1表示前置
if (time == xt) return 0; // 0表示不变
return 1; // 1表示后置
}
}
/**
* 定义一个类表示机器节点
* @author Matt
*/
public static class MachineNode implements Comparable {
int id, avail; // 机器的属性:序号、空闲时间(机器做完某一项工作的时间)
MachineNode(int i, int a) { // 构造器,传递机器的序号和时间
id = i;
avail = a;
}
@Override
public int compareTo(Object x) { // 从大到小排序
// 获取被比较机器的工作时间
int xt = ((MachineNode) x).avail;
if (avail < xt) return -1; // -1表示前置
if (avail == xt) return 0; // 0表示不变
return 1; // 1表示后置
}
}
public static int greedy(int []a, int m) {
//a的下标从1开始,所以n(作业的数目)=a.length-1
int n = a.length - 1;
int sum = 0; // 所需工作时间
if (n <= m) { // 如果机器数 > 作业数
for (int i = 0; i < n; i++) {
sum += a[i]; // 一台机器做一个作业!
}
System.out.println("为每个作业分配一台机器");
return sum; // 返回工作时间
}
// 创建一个容器ArrayList来保存作业节点
List<JobNode> d = new ArrayList<JobNode>();
// 将所有的作业节点存入List中,每一项包含序号和所需时间
for (int i = 0; i < n; i++) {
// 因为我们的a数组是从1开始的(而不是0),所以需要加1
JobNode jb = new JobNode(i+1, a[i+1]);
// 将作业加入容器
d.add(jb);
}
// 按作业的所需时间从大到小排序(调用上面的compareTo方法)
Collections.sort(d);
// 创建一个容器LinkedList保存机器节点
List<MachineNode> h = new LinkedList<MachineNode>();
for (int i = 0; i < m; i++) {
// 初始时每台机器的空闲时间均为0,因为没在工作
MachineNode x = new MachineNode(i, 0);
// 每个机器加入容器
h.add(x);
}
for (int i = 0; i < n; i++) {
// 从大到小排序
Collections.sort(h);
// 取出容器中的头元素(最大的)
MachineNode x = ((LinkedList<MachineNode>) h).peek();
System.out.println("将机器" + x.id + "从" + x.avail +"到"
+ (x.avail+d.get(i).time) + "的时间段分配给作业" +
d.get(i).id);
// 为机器分配作业
x.avail += d.get(i).time;
// 最后的sum为最长的工作时间的机器的时间
sum = x.avail;
}
return sum; // 返回工作时间
}
public static void main(String[] args) {
int []a = {0, 2, 14, 4, 16, 6, 5, 3};
int m = 3;
int sum = greedy(a,m);
System.out.println("总时间为:" + sum);
}
}
// 运行结果:
// 将机器0从0到16的时间段分配给作业4
// 将机器1从0到14的时间段分配给作业2
// 将机器2从0到6的时间段分配给作业5
// 将机器2从6到11的时间段分配给作业6
// 将机器2从11到15的时间段分配给作业3
// 将机器1从14到17的时间段分配给作业7
// 将机器2从15到17的时间段分配给作业1
// 总时间为:17
贪心算法_作业调度问题
最新推荐文章于 2024-09-14 10:34:28 发布