[java]P1065作业调度方案题解(快速输入 洛谷)

本篇文章不是原创!而是笔记

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;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值