题目描述
Description
每一个任务都有三个属性:开始时间s、结束时间f以及所产生的价值v一个任务的s到f这段时间称为其执行时间,如果两个任务的执行时间不重叠,则称它们是兼容的本题将给出若干任务及其属性,求彼此兼容且权重最大的任务子集,输出该子集所有任务产生的总价值。
Input
输入有1+n行;第1行为任务数量;剩余n行每行为一个任务的开始时间、结束时间和所产生的价值,以空格隔开,例如:
4
1 2 50
3 5 20
6 19 100
2 100 200
Output
输出应为一个数,即彼此兼容且权重最大的任务子集中所有任务产生的总价值,如
250
解题思路
根据题目定义Tast类
static class Task {
private int start; // 开始时间
private int end; // 结束时间
private int value; // 产生的价值
// 构造函数
public Task(int start, int end, int value) {
this.start = start;
this.end = end;
this.value = value;
}
}
排序
- 输入
n
个task
类对其end
字段进行排序,这样就可以从头便利的处理数据
递推思想
- 定义
dp[i]
表示前i
个任务的最大产生的价值 - 寻找冲突
- 判断第
i
个任务的开始时间在前i-1
任务所用时间的位置 - 找到第
i
个任务的开始时间执行之前的前k个任务产生的最大价值即dp[k]
- 则
dp[i] = dp[k]+task[i].value
- 不过这样的话第
i
个任务开始之后的任务没进行处理(万一第k+1
个任务的value
值无限大呢) - 所以
dp[i] = Math.max(dp[k] + task[i].value, dp[i - 1] )
这样比较准确 - 如果没找着由于排过序没找着的原因只可能时当前的第i个任务的开始时间比最开始第1个任务的结束时间都要早
- 那么
dp[i]=Math.max(dp[i - 1], task[i-1].value)
可能当前的第i
个任务值最大也可能之前累加起来的值最大
- 判断第
代码
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
public class Main {
static class Task {
private int start;
private int end;
private int value;
public Task(int start, int end, int value) {
this.start = start;
this.end = end;
this.value = value;
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
Task[] task = new Task[n];
int[] dp = new int[n + 1];
for (int i = 0; i < n; i++) {
task[i] = new Task(scanner.nextInt(), scanner.nextInt(), scanner.nextInt());
}
Arrays.sort(task, (o1,o2)-> o1.end- o2.end);
// i从1开始但是task类数组从0开始存储所以递推式需要-1
for (int i = 1; i <= n; i++) {
int search = search(task, i);
dp[i] = search == 0 ? Math.max(dp[i - 1], task[i-1].value) : Math.max(dp[search] + task[i-1].value, dp[i - 1]);
}
System.out.println(dp[n]);
}
public static int search(Task[] task, int cur) {
for (int i = 1; i <= cur; i++) {
if (task[cur - 1].start < task[i - 1].end) {
return i - 1;
}
}
return 0;
}
}