這個問題的激發是由一個在運作研究領域中,流水作業排程問題的特別例子,在限制區域的數量為2情況,有一個效率的演算法來找出最佳解答。(當區域的數量大於2的時候,這個問題被證明為是一個NP-hard問題。)這個效率的解決方法被稱作Johnsons rule. 最佳的班級區域拜訪順序會在這之後決定。
Johnson's Rule
步驟一、切割全部班級為兩個集合,一個集合Ⅰ包含所有的班級i為p(i,1) < p(i,2)和集合Ⅱ包含所有班級j為p(j,1) > p(j,2),而班級k為p(k,1) = p(k,2)者可以放在任意一個集合。
步驟二、班級在集合Ⅰ者以p(i,1)遞增的順序出發,班級在集合Ⅱ跟隨在後以p(j,2)遞減的順序。
※註:p(班級、區域)為該班級在該區域所花的時間
import java.util.*; import java.util.Scanner; public class JAVA { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int caseCount = 0; LinkedList<Integer> totalTime = new LinkedList<Integer>(); while(sc.hasNext()) { // get how many classes int classes = sc.nextInt(); // classes amount if(classes <= 0) break; /* * timeList[classes][0] = r1 time * timeList[classes][1] = r2 time */ // initialize time list int[][] timeList = new int[classes][2]; // get time input for(int i = 0; i < classes; i++) { timeList[i][0] = sc.nextInt(); timeList[i][1] = sc.nextInt(); } // step1. put them in set I and II respectively LinkedList<Integer> setI = new LinkedList<Integer>(); LinkedList<Integer> setII = new LinkedList<Integer>(); for(int i = 0; i < timeList.length; i++) { // r1 < r2, put into set I, in r1-increase order if(timeList[i][0] <= timeList[i][1]) { // setI is empty, just insert if(setI.isEmpty()) setI.add(i); // check if the first r1-time in list // is smaller than p(i,r1)? else { boolean addFlag = false; //int r1 = timeList[i][0]; for(int j = 0; j < setI.size(); j++) { //int r1_In_List = timeList[setI.get(j)][0]; if(timeList[i][0] <= timeList[setI.get(j)][0]) { setI.add(j,i); addFlag = true; break; } } if(!addFlag) setI.addLast(i); } } // r1 < r2, put into set II, in r2-decrease order else { if(setII.isEmpty()) setII.add(i); else { boolean addFlag = false; for(int j = 0; j < setII.size(); j++) { if(timeList[i][1] <= timeList[setII.get(j)][1]) { setII.add(j,i); addFlag = true; break; } } if(!addFlag) setII.addLast(i); } } } // combine the set and make the correct sequence LinkedList<Integer> sequence = new LinkedList<Integer>(); while(!setI.isEmpty()) sequence.add(setI.poll()); while(!setII.isEmpty()) sequence.add(setII.pollLast()); // release memory setI = null; setII = null; // step2. start counting time int r1Time = 0; int r2Time = 0; r1Time += timeList[sequence.getFirst()][0]; // must be add r2Time += timeList[sequence.getFirst()][1] + r1Time; for(int i = 1; i < sequence.size(); i++) { // move i th class to r1 r1Time += timeList[sequence.get(i)][0]; // i th class played r1 over // try to query r2 isEmpty? // if r2Time > r1Time mean r2 is still busying. if(r1Time > r2Time) { r2Time = r1Time; } else { // r2 is available now!! } // move i th class to r2 r2Time += timeList[sequence.get(i)][1]; } totalTime.add(r2Time); } for(int i = 1; i < totalTime.size() + 1; i++) { System.out.println(i + " " + totalTime.get(i-1)); } } }
這是沒有debug版的較乾淨程式碼,我在寫的時候還另外做了debug版,看哪天再release出來.
No comments:
Post a Comment