最近有个朋友问了一个算法分析的题目,感觉有点意思就在这里简单说一下自己的思路吧!
题目:
突击战:
你有 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 (824923282@qq.com)
*
*/
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);
}
}
}