题目的核心点:因为输入是一口气把所有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;
}
}
}

京公网安备 11010502036488号