Java求解貪心算法多機調度問題

1、問題描述

 設有n個獨立的作業{1, 2, …, n}, 由m臺相同的機器進行加工處理. 作業i所需時間爲t i. 約定:任何作業可以在任何一臺機器上加工處理, 但未完工前不允許中斷處理,任何作業不能拆分成更小的子作業。要求給出一種作業調度方案,使所給的n 個作業在儘可能短的時間內由m臺機器加工處理完成。 

 多機調度問題是一個NP完全問題,到目前爲止還沒有完全有效的解法。對於這類問題,用貪心選擇策略有時可以設計出一個比較好的近似算法。

 2、貪心算法求解思路

 採用最長處理時間作業優先的貪心策略:
 當n≤m時, 只要將機器i的[0, ti]時間區間分配給作業i即可。
 當n>m時, 將n個作業依其所需的處理時間從大到小排序,然後依次將作業分配給空閒的處理機。

  具體代碼如下:

package 貪心;

//public class Greedy
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * @author 葛帥帥
 */
public class Greedy {
    public static class JobNode implements Comparable{
        int id;//作業的標號
        int time;//作業時間
        public JobNode(int id,int time){
            this.id=id;
            this.time=time;
        }
        @Override
        public int compareTo(Object x) {//按時間從大到小排列
            int times=((JobNode)x).time;
            if(time>times) return -1;
            if(time==times) return 0;
            return 1;

        }
    }
    public static class MachineNode implements Comparable{
        int id;//機器的標號
        int avail;//機器空閒的時間(即機器做完某一項工作的時間)
        public MachineNode(int id,int avail){
            this.id=id;
            this.avail=avail;
        }
        @Override
        public int compareTo(Object o) {//升序排序,LinkedList的first爲最小的
            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;//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<JobNode> d=new ArrayList<JobNode>();//d保存所有的作業
        for(int i=0;i<n;i++){//將所有的作業存入List中,每一項包含標號和時間
            JobNode jb=new JobNode(i+1,a[i]);
            d.add(jb);
        }
        Collections.sort(d);//對作業的List進行排序
        LinkedList<MachineNode> h=new LinkedList<MachineNode>();//h保存所有的機器
        for(int i=1;i<=m;i++){//將所有的機器存入LinkedList中
            MachineNode x=new MachineNode(i,0);//初始時,每臺機器的空閒時間(完成上一個作業的時間)都爲0
            h.add(x);
        }
        int test=h.size();
        for(int i=0;i<n;i++){
              Collections.sort(h);
            MachineNode x=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=x.avail;
        }
        return sum;
    }
    public static void main(String[] args) {
        int[] a={14,2,3,4,5,6,8,8,9};
              // 1,2,3,4,5,6,7 ,8,9
        int m=3;
        int sum=greedy(a,m);
        System.out.println("總時間爲:"+sum);
    }
}
/**
 運行結果:
 將機器1從0到14的時間段分配給作業1
 將機器2從0到9的時間段分配給作業9
 將機器3從0到8的時間段分配給作業7
 將機器3從8到16的時間段分配給作業8
 將機器2從9到15的時間段分配給作業6
 將機器1從14到19的時間段分配給作業5
 將機器2從15到19的時間段分配給作業4
 將機器3從16到19的時間段分配給作業3
 將機器3從19到21的時間段分配給作業2
 總時間爲:21
 */

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章