演算法導論之貪心演算法:帶懲罰的任務排程演算法
阿新 • • 發佈:2019-01-30
帶懲罰的任務排程問題:
單處理器上帶截止時間和懲罰的單位時間任務排程問題有以下輸入:
1、n個單位時間任務的集合S={a1,a2,……,an};
2、n個整數截止時間d1,d2,……,dn,每個di滿足1<=di<=n,我們期望任務ai在時間di之前完成。
3、n個非負權重或者懲罰w1,w2,……,wn,若任務ai在時間di之前沒有完成,我們就會受到wi這麼多的懲罰,如果任務在截止時間之前完成,則不會受到懲罰。
(單位時間任務是嚴格需要一個時間單位來完成的作業)
在演算法中我們定義延遲:如果方案中一個任務在截止時間後完成。都則就是提前。
提前優先形式:將提前的任務都置於延遲任務之前。
排程方案有規範形式:提前任務都在延遲任務之前,且提前任務按截止時間單調遞增的順序排列。
程式碼實現如下:
package cc.wsyw126.algorithms; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; /* 問題描述: 在單處理器上具有期限和懲罰的單位時間任務排程問題(課本P239) 實驗要求: (1)實現這個問題的貪心演算法 (2)將每個wi 替換為 max{w1,w2,...,wn}-wi,執行演算法比較結果*/ /** * @author WSYW126 * @version 建立時間:2016年6月4日 下午8:29:32 類說明:Alljava */ public class TaskSchedul { private List<Task> tasks = null; // 所有任務 private List<Task> earlyTasks = null; // 早任務 private List<Task> lateTasks = null; // 晚任務 private Comparator<Task> comparator_d= null; private Comparator<Task> comparator_w = null; public static void main(String[] args) { //int[] d = {4, 2, 4, 3, 1, 4, 6}; // 各個任務的deadline //int[] w = {70, 60, 50, 40, 30, 20, 10}; // 各個任務的懲罰 int[] d = {5, 3, 1, 4, 6, 4, 2, 2}; // 各個任務的deadline int[] w = {60, 70, 40, 50, 10, 30, 20, 5}; // 各個任務的懲罰 TaskSchedul ts = new TaskSchedul(d, w); ts.scheduleTask(); // 任務排程 ts.printList(); // 輸出資訊 System.out.println("----------------------------用max{w1,12,...,wn}-wi替換後的結果-----------------------------"); ts.rescheduleTask(); // 用max{w1,12,...,wn}-wi替換wi後,任務排程 ts.printList(); // 輸出資訊 } public void rescheduleTask() { // 用max{w1,12,...,wn}-wi替換wi int max = tasks.get(0).getWeight(); // 在init()函式中已經將tasks中的任務按懲罰大小降序排序 for (Task task : tasks) { task.setWeight(max - task.getWeight()); } System.out.print("任務集為:"); for (Task task : tasks) { System.out.print("a" + (task.getId() + 1) + "(d:" + task.getDeadLine() + ",w:" + task.getWeight() + ") "); } System.out.println(); Collections.sort(tasks, comparator_w); // 將任務按懲罰大小降序排序 earlyTasks = new ArrayList<Task>(); lateTasks = new ArrayList<Task>(); scheduleTask(); } public void scheduleTask() { // 時間複雜度為O(n^2) int n = tasks.size(); int[] NA = new int[n]; // 標記,用來判斷任務集是否獨立 int[] count = new int[n]; // 標記,ai之前,截止時間小於ai的個數 Arrays.fill(count, 0); for (int i = 0; i < n; i++) { // NA[0..n-1]; NA[i] = 0; } for (int i = 0; i < n && NA[i] == 0; i++) { int flag = count[i] + 1; Task task = tasks.get(i); for (int j = i + 1; j < n; j++) { if (NA[i] != 0 || NA[j] != 0) continue; Task temp = tasks.get(j); if (task.getDeadLine() >= temp.getDeadLine()) { flag++; if (flag > task.getDeadLine()) { lateTasks.add(temp); NA[j] = 1; } } if (task.getDeadLine() <= temp.getDeadLine()) { count[j] = count[j] + 1; } } } for (int i = 0; i < n; i++) { if (NA[i] == 0) { earlyTasks.add(tasks.get(i)); } } Collections.sort(earlyTasks, comparator_d); } public TaskSchedul(int[] d, int[] w) { initComparator(); init(d, w); } public void init(int[] d, int[] w) { // 匯入初始任務 tasks = new ArrayList<Task>(); earlyTasks = new ArrayList<Task>(); lateTasks = new ArrayList<Task>(); int n = d.length; for (int i = 0; i < n; i++) { Task t = new Task(); t.setId(i); t.setDeadLine(d[i]); t.setWeight(w[i]); tasks.add(t); } System.out.print("任務集為:"); for (Task task : tasks) { System.out.print("a" + (task.getId() + 1) + "(d:" + task.getDeadLine() + ",w:" + task.getWeight() + ") "); } System.out.println(); Collections.sort(tasks, comparator_w); // 將任務按懲罰大小降序排序 } public void initComparator() { comparator_d = new Comparator<Task>() { // 按deadline升序排列任務 public int compare(Task t1, Task t2) { if (t1.getDeadLine() > t2.getDeadLine()) { return 1; } else if (t1.getDeadLine() == t2.getDeadLine()) { return 0; } else { return -1; } } }; comparator_w = new Comparator<Task>() { // 按(懲罰)w降序排列任務 public int compare(Task t1, Task t2) { if (t2.getWeight() > t1.getWeight()) { return 1; } else if (t2.getWeight() == t1.getWeight()) { return 0; } else { return -1; } } }; } public void printList() { int punish = 0; System.out.print("貪心演算法選擇任務為:"); for (Task t : earlyTasks) { System.out.print("a" + (t.getId() + 1) + " "); } System.out.print("\n被懲罰任務為:"); for (Task t : lateTasks) { System.out.print("a" + (t.getId() + 1) + " "); } System.out.print("\n總的懲罰數為:"); for (Task t : lateTasks) { punish += t.getWeight(); } System.out.println(punish + ""); } } class Task { // 任務定義 private int id; private int deadLine; private int weight; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getDeadLine() { return deadLine; } public void setDeadLine(int deadLine) { this.deadLine = deadLine; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } }
時間複雜度分析:
在上面的過程中,我們使用scheduleTask函式,它的時間複雜度為O(n^2)。
因此由scheduleTask決定我們的演算法的時間複雜度為O(n^2)。
參考資料:
演算法導論
備註:
轉載請註明出處:http://blog.csdn.net/wsyw126/article/details/51586443
作者:WSYW12