經典演算法分析與設計——突擊戰
阿新 • • 發佈:2019-01-07
最近有個朋友問了一個演算法分析的題目,感覺有點意思就在這裡簡單說一下自己的思路吧!
題目:
突擊戰:
你有 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:交代任務時間為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);
}
}
}