本篇文章不是原创!而是笔记
import java.util.Scanner;
public class P1065作业调度方案_改进版 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m, n;
m = sc.nextInt();
n = sc.nextInt();
// 记录当前工件要完成第几道工序 并进行初始化
int[] workpiece = new int[n + 1];
for (int i = 1; i <= n; i++) {
workpiece[i] = 1;
}
// 记录第i件工件在完成之前的工序后最早开始时间 初始化为0
int[] earlyTime = new int[n + 1];
// 记录安排顺序
int[] arrangeOrder = new int[m * n];
for (int i = 0; i < m * n; i++) {
arrangeOrder[i] = sc.nextInt();
}
// 记录第i件工件第j道工序的机器号和加工时常
Info[][] info = new Info[n + 1][m + 1];
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int machineNum = sc.nextInt();
info[i][j] = new Info();
info[i][j].machineNum = machineNum;
}
}
// 记录完成时间
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
int time = sc.nextInt();
info[i][j].time = time;
}
}
// 记录第i个机器的时间线 并初始化 false表示该时间点不忙 true表示在忙
// 注意每个机器时间线是理论上0-无穷大 但是计算机无法表示无穷数据,且模拟数据量不会过大 因此我们时间线设置到0-10000即可
boolean[][] lineTime = new boolean[m + 1][10001];
for (int i = 1; i <= m; i++) {
for (int j = 0; j <= 10000; j++) {
lineTime[i][j] = false;
}
}
// 开始进行遍历 cur代表当前去除的工件号
for (Integer cur : arrangeOrder) {
int order = workpiece[cur]; // order表示该工件要完成的工序
workpiece[cur]++;
int eralytime = earlyTime[cur]; // 带工序的最早开始时间
Info curInfo = info[cur][order]; // 该工序的信息
for (int i = eralytime; i <= 10000; i++) {
if (isArrange(i, curInfo, lineTime)) {
updateTime(i, curInfo, lineTime);
earlyTime[cur] = i + curInfo.time;
break;
}
}
}
// 从最后时间中查找最大值
int res = -1;
for (int i = 1; i <= n; i++) {
res = Math.max(res, earlyTime[i]);
}
System.out.print(res);
sc.close();
return;
}
// 是否可以安排时间
static boolean isArrange(int startTime, Info inf, boolean[][] lineTime) {
int len = inf.time;
int num = inf.machineNum;
// 对末尾时间的处理我们认为其完成在末尾时间左侧一点
for (int i = startTime; i < startTime + len; i++) {
if (lineTime[num][i])
return false;
}
return true;
}
// 更新时间线
static void updateTime(int startTime, Info inf, boolean[][] lineTime) {
int len = inf.time;
int num = inf.machineNum;
// 对末尾时间的处理我们认为其可以作为下一个开始点因此设为忙
for (int i = startTime; i < startTime + len; i++) {
lineTime[num][i] = true;
}
}
// 记录工序所需机器以及完成时间
static class Info {
public int machineNum;
public int time;
}
}