题意:给一组任务,有各自的截止日期和收益,每个任务耗时一个单位时间,要求实现实现收益最大化,输出任务数和收益。
题解:思路还是蛮简单的,利用贪心算法,先建立一个给定数据中最大截至日期大小的数组代表几天的任务怎么分配,每次在判断一个任务插不插入时,先看截至日期之前有没有空,有空就插入,没空的话就找收益最小的一天。
这地方有个体现贪心的细节:是在找截止日期前数组最小值时,假如第一天和第二天相同,且都是最小值,我们应该选择后者,因为如果把当前值放进第一天,后面如果出现收益比当前值大的第一天就会把当前值挤掉,举个例子,数组里面前两个值为10,10,当前为第二天截止,收益为20的任务,如果我们放到了第一天,假如又来了一个第一天截止收益为30的任务,最后结果为30,10;如果我们放在了第二天,结果就会变为30,20。
代码:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int e_num = scan.nextInt();//测试数
while(e_num>0){
int tasknum = scan.nextInt();
int[][] data = new int[tasknum][3];
for(int i=0;i<tasknum;i++){
for(int j=0;j<3;j++){
data[i][j]=scan.nextInt();
}
}
int maxddl = 0;
for(int i=0;i<tasknum;i++){
maxddl = Math.max(maxddl,data[i][1]);
}
int[] task = new int[maxddl];
Arrays.fill(task,0);
for(int i=0;i<tasknum;i++){
boolean flag=false;//当前是否有空做
int currentddl = data[i][1];
//截止日之前,有空就做
for(int j=currentddl;j>0;j--){
if(task[j-1]==0){
task[j-1]=data[i][2];
flag=true;
break;
}
}
//没空就找截止之前的最小值
if(flag==false){
int pos=-1;
int min = Integer.MAX_VALUE;
for(int j=currentddl;j>0;j--){
if(task[j-1]<min){
min=task[j-1];
pos=j-1;
}
}
if(data[i][2]>=min){
task[pos]=data[i][2];
}
}
}
int result=0;
int count=0;
for(int i=0;i<maxddl;i++){
result += task[i];
if(task[i]!=0){
count++;
}
// System.out.println(task[i]);
}
System.out.println(count+" "+result);
e_num --;
}
}
}