1. 程式人生 > >經典演算法分析與設計——突擊戰

經典演算法分析與設計——突擊戰

最近有個朋友問了一個演算法分析的題目,感覺有點意思就在這裡簡單說一下自己的思路吧!

題目:

突擊戰:

你有 n 個部下, n 個任務,你計劃讓部下 i 去做任務 i  (1<=i< =n ) ,但部下還不知道任務 的內容,需要你為每個部下解釋任務內容(即交代任務)。第 i 個部下需要你花 B(i) 分鐘交 代任務,然後他會立刻、獨立地、無間斷地執行 J( i) 分鐘後完成任務。你每次只能給一個 部下交代任務,但部下們可以同時執行各自的任務。 問題:交代任務的順序不同,完成所有任務所用的時間也不同。你需要考慮的是交代任務的 順序,在最短的時間內完成所有任務。 輸入:每個部下交代任務需要的時間 B(i) 和執行自己任務需要的時間 J(i) ,其中 1<=i< =n 

輸入格式:第一行輸入部下數 n (它也是任務數) 後面的 n 行,每行兩個數字,分別對應 B(i) 和 J (i) 

輸出: 1~ n 的一個排列(對應 n 個部下的交代任務次序),以及這種安排下所有任務的完成 時間

演算法分析:

根據題目我們可以知道的條件:

  1. 交代任務只能是先交代完本次才能進行下一次交代,也就是說不管怎樣排列它們的總時間都是不變的,因此這個不能作為優化的點
  2. 士兵執行任務是可以並列執行的,也就是如果將任務執行的時間安排得緊湊點,讓執行任務的等待時間變得最低就可以達到最優,也就是說只要按士兵執行任務時由大到小進行先後排列即可

驗證思路:

假設存在兩個任務,任務1:交代任務時間為1分鐘,執行任務時間為2分鐘;任務2:交代任務時間為3分鐘,執行任務時間為4分鐘

如果直接進行排序:

直接進行排序

按執行任務時間由大到小排序:

按執行任務時間由大到小排序

程式碼實現(java):

package assault;

import java.util.*;

/**
 * 突擊戰演算法分析:
 * 1、交代任務只能是先交代完本次才能進行下一次交代,也就是說不管怎樣排列它們的總時間都是不變的,
 * 因此這個不能作為優化的點
 * 2、士兵執行任務是可以並列執行的,也就是如果將任務執行的時間安排得緊湊點,
 * 讓執行任務的等待時間變得最低就可以達到最優,也就是說只要按士兵執行任務時由大到小進行先後排列即可
 * @author jodenhe ([email protected]
) * */ public class Main implements Comparable { int index;//任務標記 int b;//交代任務時間 int j; //執行任務時間 public Main(int index,int b, int j) { this.index = index; this.b = b; this.j = j; } /** * 重新比較方法,實現由大到小排列 */ @Override public int compareTo(Object m) { return (j > ((Main) m).j ? -1 : (j == ((Main) m).j) ? 0 : 1); } public static void main(String arg[]) { Scanner cin = new Scanner(System.in); int casenum=0; while (cin.hasNext()) { final int n = cin.nextInt(); Main[] m = new Main[n]; for (int i = 0; i < n; i++) { m[i]=new Main(i+1,cin.nextInt(),cin.nextInt()); } Arrays.sort(m); int time=0,temp=0; System.out.print("1~ n的一個排列:"); for(int i=0;i<n;i++){ System.out.print(m[i].index); if (i != n-1) { System.out.print(","); }else{ System.out.println(); } time+=m[i].b; if((temp-=m[i].b)<=0)temp=0; if(temp<m[i].j)temp=m[i].j; } time+=temp; System.out.println("Case "+(++casenum)+"(所有任務的完成時間): "+time); } } }