贪心算法_作业调度问题

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值