You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.3 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2021_12_5_week;
import java.util.Arrays;
import java.util.PriorityQueue;
// 来自hulu
// 有n个人m个任务任务之间有依赖记录在int[][] depends里
// 比如: depends[i] = [a, b]表示a任务依赖b任务的完成
// 其中 0 <= a < m0 <= b < m
// 1个人1天可以完成1个任务每个人都会选当前能做任务里标号最小的任务
// 一个任务所依赖的任务都完成了,该任务才能开始做
// 返回n个人做完m个任务需要几天
public class Code02_DoAllJobs {
public static int days(int n, int m, int[][] depends) {
if (n < 1) {
return -1;
}
if (m <= 0) {
return 0;
}
// nexts[0] = {1,4}
int[][] nexts = nexts(depends, m);
int[] indegree = indegree(nexts, m);
// 工人队列!
PriorityQueue<Integer> workers = new PriorityQueue<>();
for (int i = 0; i < n; i++) {
workers.add(0);
}
// zeroIn 放着工作,放着可以开始做的工作,不能做的任务,不在其中
// 小根堆:标号小的任务,一定要先做!
PriorityQueue<Integer> zeroIn = new PriorityQueue<>();
for (int i = 0; i < m; i++) {
if (indegree[i] == 0) {
zeroIn.add(i);
}
}
// start[i] i之前必须完成的任务占了几天导致i任务只能从那天开始
int[] start = new int[m];
// 完成所有任务的最大天数
int finishAll = 0;
int done = 0;
while (!zeroIn.isEmpty()) { // 有任务可做
// 当前可以做的任务中,标号最小的任务
int job = zeroIn.poll();
// 当前可用的工人里,最早醒的!
int wake = workers.poll();
// job 何时完成呢?
// (工人醒来,开工时间)最晚的!+1
int finish = Math.max(start[job], wake) + 1;
finishAll = Math.max(finishAll, finish);
done++;
// 消除影响
for (int next : nexts[job]) {
start[next] = Math.max(start[next], finish);
if (--indegree[next] == 0) {
zeroIn.add(next);
}
}
workers.add(finish);
}
return done == m ? finishAll : -1;
}
public static int[][] nexts(int[][] depends, int m) {
Arrays.sort(depends, (a, b) -> a[1] - b[1]);
int n = depends.length;
int[][] nexts = new int[m][0];
if (n == 0) {
return nexts;
}
int size = 1;
for (int i = 1; i < n; i++) {
if (depends[i - 1][1] != depends[i][1]) {
int from = depends[i - 1][1];
nexts[from] = new int[size];
for (int k = 0, j = i - size; k < size; k++, j++) {
nexts[from][k] = depends[j][0];
}
size = 1;
} else {
size++;
}
}
int from = depends[n - 1][1];
nexts[from] = new int[size];
for (int k = 0, j = n - size; k < size; k++, j++) {
nexts[from][k] = depends[j][0];
}
return nexts;
}
public static int[] indegree(int[][] nexts, int m) {
int[] indegree = new int[m];
for (int i = 0; i < m; i++) {
for (int j = 0; j < nexts[i].length; j++) {
indegree[nexts[i][j]]++;
}
}
return indegree;
}
public static void main(String[] args) {
// 2 -> 5 -> 6
// |
// v
// 1 -> 4 -> 7
// ^
// |
// 0 -> 3
// 两个人
// {12} 工人队列
// 0 : 干0号工作 1
// 0 : 干1号工作 1
// 1 : 干2号工作2
int[][] d = {
{ 3, 0 },
{ 4, 1 },
{ 5, 2 },
{ 4, 3 },
{ 6, 5 },
{ 7, 4 },
{ 7, 6 }
};
System.out.println(days(3, 8, d));
System.out.println(days(2, 8, d));
}
}