题目的核心点:因为输入是一口气把所有idea都输入进来了,所以在程序中需要为每个程序员维护一个当前时间,程序员在所有idea中挑idea的时候,只有当程序员的当前时间大于idea的提出时间才可能会处理这个idea。接着那如何从多个可能会处理的idea中挑出一个呢?根据题目意思是,先在PM层面根据规则为每个PM挑一个,然后程序员再根据规则从中挑一个。
实现的核心点:
1. 因为有多个程序员,每个程序员的当前时间都不一样,所以我们每次在处理idea的时候,需要挑出当前时间最小的程序员,先让这个程序员去挑idea,每次挑出当前时间最小的程序员可以用小根堆实现。
2. 如果本次的程序员一个idea都没有挑出来,那么就表示当前所有的idea的提出时间都大于这个程序员的当前时间,这个时候我们需要将这个程序员的当前时间向前推进1。
题外话:感觉本地重点考察的不是单纯的数据结构与算法,而是面向对象的思想。以下的代码实现为了精简同时保持好的可读性,对于类的属性没有使用getter/setter。
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int N = sc.nextInt(); //PM数 int m = sc.nextInt(); //programmer数 int p = sc.nextInt(); //idea数 ArrayList<Idea> ideas = new ArrayList<>(p); //需求池 for (int i = 0; i < p; i++) ideas.add(new Idea(i, sc.nextInt(), sc.nextInt(), sc.nextInt(), sc.nextInt())); sc.close(); PriorityQueue<Programmer> programmers = new PriorityQueue<>(m, Comparator.comparingInt(o -> o.nowTime)); //小根堆,找到最先有空的程序员 for (int i = 0; i < m; i++) programmers.add(new Programmer(1)); //每个程序员的初始时间都是1 int[] res = new int[p]; //这个数组保存的就是最后的结果,因为要按需求输入的顺序输出每个需求的完成时间,所以在idea里面保留了一个seq,最后会将需求完成的时间按seq写入数组 while (!ideas.isEmpty()) { //处理需求池中的需求 Programmer programmer = programmers.remove(); int seq = programmer.handle(ideas, N); if (seq != -1) res[seq] = programmer.nowTime; programmers.add(programmer); } for (int i : res) System.out.println(i); } } class Idea { int seq; int pmNo; int createTime; int priority; int duration; public Idea(int seq, int pmNo, int createTime, int priority, int duration) { this.seq = seq; this.pmNo = pmNo; this.createTime = createTime; this.priority = priority; this.duration = duration; } } class Programmer { int nowTime; public Programmer(int nowTime) { this.nowTime = nowTime; } private Idea selectIdea(List<Idea> ideas, int pms) { Idea[] tpIdeaOfPms = new Idea[pms]; //top priority idea of PMs,每个PM最想完成的需求 for (Idea idea : ideas) {//挑出每个PM最想完成的需求 if (this.nowTime < idea.createTime) continue; //这个需求提出的时间大于当前程序员所处的时间,所以现在不予考虑,直接pass if (tpIdeaOfPms[idea.pmNo - 1] == null) { tpIdeaOfPms[idea.pmNo - 1] = idea; continue; } if (idea.priority < tpIdeaOfPms[idea.pmNo - 1].priority) { continue; } if (idea.priority > tpIdeaOfPms[idea.pmNo - 1].priority) { tpIdeaOfPms[idea.pmNo - 1] = idea; continue; } if (idea.duration > tpIdeaOfPms[idea.pmNo - 1].duration) { continue; } if (idea.duration < tpIdeaOfPms[idea.pmNo - 1].duration) { tpIdeaOfPms[idea.pmNo - 1] = idea; continue; } if (idea.createTime > tpIdeaOfPms[idea.pmNo - 1].createTime) { continue; } if (idea.createTime < tpIdeaOfPms[idea.pmNo - 1].createTime) { tpIdeaOfPms[idea.pmNo - 1] = idea; continue; } } Idea selectedIdea = null; //该程序员最终选择的需求 for (Idea idea : tpIdeaOfPms) { //从每个PM最想完成的需求中挑出一个 if (idea == null) continue; if (selectedIdea == null) selectedIdea = idea; if (idea.duration < selectedIdea.duration) { selectedIdea = idea; } else if (idea.duration == selectedIdea.duration && idea.pmNo < selectedIdea.pmNo) { selectedIdea = idea; } } return selectedIdea; } public int handle(List<Idea> ideas, int pms) { Idea selectedIdea = this.selectIdea(ideas, pms); if (selectedIdea != null) { //处理pm的需求 nowTime += selectedIdea.duration; ideas.remove(selectedIdea); return selectedIdea.seq; } else { //当前时间pm没有提需求,时间继续向前 nowTime += 1; return -1; } } }