题目描述
为了找到自己满意的工作,牛牛收集了每种工作的难度和报酬。牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。在牛牛选定了自己的工作后,牛牛的小伙伴们来找牛牛帮忙选工作,牛牛依然使用自己的标准来帮助小伙伴们。牛牛的小伙伴太多了,于是他只好把这个任务交给了你。
输入描述
每个输入包含一个测试用例。 每个测试用例的第一行包含两个正整数,分别表示工作的数量N(N<=100000)和小伙伴的数量M(M<=100000)。 接下来的N行每行包含两个正整数,分别表示该项工作的难度Di(Di<=1000000000)和报酬Pi(Pi<=1000000000)。 接下来的一行包含M个正整数,分别表示M个小伙伴的能力值Ai(Ai<=1000000000)。 保证不存在两项工作的报酬相同。
输出描述
对于每个小伙伴,在单独的一行输出一个正整数表示他能得到的最高报酬。一个工作可以被多个人选择。
输入示例
3 3 1 100 10 1000 1000000000 1001 9 10 1000000000
输出示例
100 1000 1001
分析
这道题看似像动态规划中的01背包问题,但是不是,一开始我以为是动态规划问题,直接就写了个01背包,发现java内存溢出了,其实这道题的精髓在于第一句话:牛牛选工作的标准是在难度不超过自身能力值的情况下,牛牛选择报酬最高的工作。就是说在工作难度小于等于自身能力的工作中,选择其中最高的报酬,所以说这道题考的就不是动规,而是排序和查找
解法:代码中做了详细的注释,一看便知,我已经在牛客网上运行通过了,可以直接复制
import java.util.Arrays;
import java.util.Scanner;
import java.util.TreeMap;
public class 牛牛找工作 {
public static void main(String[] args) {
//输入流
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();//n表示工作的数量
int m = sc.nextInt();//m表示同学的数量
// jobs数组 n行2列 n行表示n个工作,第一列表示工作的难度, 第二列表示工作的报酬
int[][] jobs = new int[n][2];
for (int i=0;i<n;i++){
jobs[i][0] = sc.nextInt();//表示工作的难度
jobs[i][1] = sc.nextInt();//表示工作的报酬
}
//jobs数组排序
Arrays.sort(jobs, ((o1, o2) -> o1[0]-o2[0]));//按照工作难度从小到大排序
//很重要 我们把每个工作的报酬设置为 难度比他小的这些工作中的最大报酬
for (int i=1;i<jobs.length; i++){
jobs[i][1] = Math.max(jobs[i - 1][1], jobs[i][1]);
}
//将job数组存储到TreeMap中,其中,key=难度,value=最大报酬
TreeMap<Integer, Integer> map = new TreeMap<>();
for (int i=0; i<jobs.length; i++){
map.put(jobs[i][0], jobs[i][1]);
}
//输入每个同学的能力ability
for (int i=0;i<m;i++){
int ability = sc.nextInt();
//返回的是小于等于ability的最大key,其实这里就是在找这个能力下的最大工作难度
Integer key = map.floorKey(ability);
if (key != null)
//找到这个难度对应的最大报酬就是我们想得到的最大报酬
System.out.println(map.get(key));
else
System.out.println(0);
}
}
}