1. 程式人生 > >演算法導論之貪心演算法:帶懲罰的任務排程演算法

演算法導論之貪心演算法:帶懲罰的任務排程演算法

帶懲罰的任務排程問題

單處理器上帶截止時間和懲罰的單位時間任務排程問題有以下輸入:

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