链接:https://www.nowcoder.com/questionTerminal/f76b7bc64e554edaa53d8e0d84f921c5
来源:牛客网
产品经理(PM)有很多好的idea,而这些idea需要程序员实现。现在有N个PM,在某个时间会想出一个 idea,每个 idea 有提出时间、所需时间和优先等级。对于一个PM来说,最想实现的idea首先考虑优先等级高的,相同的情况下优先所需时间最小的,还相同的情况下选择最早想出的,没有 PM 会在同一时刻提出两个 idea。
同时有M个程序员,每个程序员空闲的时候就会查看每个PM尚未执行并且最想完成的一个idea,然后从中挑选出所需时间最小的一个idea独立实现,如果所需时间相同则选择PM序号最小的。直到完成了idea才会重复上述操作。如果有多个同时处于空闲状态的程序员,那么他们会依次进行查看idea的操作。
求每个idea实现的时间。
输入第一行三个数N、M、P,分别表示有N个PM,M个程序员,P个idea。随后有P行,每行有4个数字,分别是PM序号、提出时间、优先等级和所需时间。输出P行,分别表示每个idea实现的时间点。
输入描述:
输入第一行三个数N、M、P,分别表示有N个PM,M个程序员,P个idea。随后有P行,每行有4个数字,分别是PM序号、提出时间、优先等级和所需时间。全部数据范围 [1, 3000]。
输出描述:
输出P行,分别表示每个idea实现的时间点。
示例1
输入
2 2 5 1 1 1 2 1 2 1 1 1 3 2 2 2 1 1 2 2 3 5 5
AC通过代码
//用程序员的下次开始时间作为时间戳,用堆维护,每次取下次时间最小的,选择任务前先将上次检查点到提交时间<=当前时间的idea入每个PM相应的待执行队列(优先级队列)
//然后从每个PM的队列中取时间最短的
//很多ac 30%的问题在于,当程序员完成手头工作,PM队列中还有待执行任务的情况
//对于这种情况,我的做法是如果每个PM队列都为空,检查是否还有未入队列的idea,如果有,从中选提交时间最小的,并从这个时间开始工作,将未入队的入队,程序员选择任务
//上一步中,如果一个程序员触发了时间跳跃(即程序员的空闲时间),那么必须更新其他尚未跳跃的程序员的下次工作时间,做法就是和他选到的工作比较,如果他选到的工作的提交时间
//比他工作时间大,说明他需要更新,更新为选到的工作的提交时间即可
import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.PriorityQueue; import java.util.Scanner; public class Main { static class Idea implements Comparable<Idea>{ int tm; int cost; int pr; int done; public Idea(int tm,int cost,int pr) { super(); this.tm = tm; this.pr = pr; this.cost = cost; } @Override public int compareTo(Idea o) { // TODO Auto-generated method stub //优先级高,时间小,提出早 int a; if(pr!=o.pr) a=pr-o.pr; else if(cost!=o.cost) a=o.cost-cost; else a=o.tm-tm; return -a; } } static class Coder implements Comparable<Coder>{ int id; int nextWorkTime; public Coder(int id, int nextWorkTime) { super(); this.id = id; this.nextWorkTime = nextWorkTime; } @Override public int compareTo(Coder o) { // TODO Auto-generated method stub return -1*(o.nextWorkTime-nextWorkTime); } } int np,nm,ni; ArrayList<Idea>[] data; PriorityQueue<Idea>[] needDo; int[] lastcheckedIndex; PriorityQueue<Coder> coder; ArrayList<Idea> input=new ArrayList<>(); int init() { int sttime=Integer.MAX_VALUE; Scanner is=new Scanner(System.in); np=is.nextInt(); nm=is.nextInt(); ni=is.nextInt(); needDo=new PriorityQueue[np]; lastcheckedIndex=new int[np]; Arrays.fill(lastcheckedIndex, -1); data=new ArrayList[np]; for(int i=0;i<np;i++) { data[i]=new ArrayList<Idea>(); needDo[i]=new PriorityQueue<Idea>(); } for(int i=0;i<ni;i++) { int ipm=is.nextInt(); int itm=is.nextInt(); int ipr=is.nextInt(); int ict=is.nextInt(); sttime=Math.min(itm, sttime); Idea idea=new Idea(itm, ict, ipr); data[ipm-1].add(idea); input.add(idea); } coder=new PriorityQueue<>(); for(int i=0;i<nm;i++) { coder.add(new Coder(i+1,sttime)); } is.close(); for(ArrayList<Idea> arr:data) Collections.sort(arr,new Comparator<Idea>() { @Override public int compare(Idea o1, Idea o2) { // TODO Auto-generated method stub return o1.tm-o2.tm; } }); return sttime; } public static void main(String[] args) { // TODO Auto-generated method stub Main test=new Main(); int curtime=test.init(); while(true) { Coder freeCoder=test.coder.poll(); curtime=freeCoder.nextWorkTime; test.enNeedDO(curtime); Idea todo=test.getTodo(); if(todo==null) { int jumptime=Integer.MAX_VALUE; boolean done=true; for(int i=0;i<test.lastcheckedIndex.length;i++) { int j=test.lastcheckedIndex[i]+1; if(j<test.data[i].size()) { done=false; jumptime=Math.min(jumptime, test.data[i].get(j).tm); } } if(done)break; curtime=jumptime; test.enNeedDO(curtime); todo=test.getTodo(); } if(todo.tm>curtime) curtime=todo.tm; todo.done=todo.cost+curtime; freeCoder.nextWorkTime=curtime+todo.cost; test.coder.add(freeCoder); } for(Idea idea:test.input) System.out.println(idea.done); } void enNeedDO(int curtime) { for(int i=0;i<data.length;i++) { int j=lastcheckedIndex[i]+1; while(j<data[i].size()&&data[i].get(j).tm<=curtime) { needDo[i].add(data[i].get(j)); lastcheckedIndex[i]=j++; } } } Idea getTodo() { int costmin=Integer.MAX_VALUE; int costminPM=-1; for(int i=0;i<needDo.length;i++) { if(needDo[i].peek()!=null&&needDo[i].peek().cost<costmin) { costmin=needDo[i].peek().cost; costminPM=i; } } if(costminPM==-1) return null; return needDo[costminPM].poll(); } }