Java教程

P1065 [NOIP2006 提高组] 作业调度方案

本文主要是介绍P1065 [NOIP2006 提高组] 作业调度方案,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

洛谷的模拟绿题

传送门 :https://www.luogu.com.cn/problem/P1065 

题目中涉及的变量比较多,题目也比较难理解,最好在已经理解题目的意思后再看题解。题解写在代码段的注释里,很清晰。如果实在看不懂也可以上B站找视频。

#include<iostream>
using namespace std;
typedef struct infomation {
	int number;
	int time;
}infomation;

//infomation用来定义每个工件的每道工序的信息
//即该工序在哪个机器上以及需要花费的时间

typedef struct cur {
	int now;
	int lasttime;
}cur;

//cur用来定义每个工件的现在状态
//即该工件现在进行了几道工序和该工件目前工序的最晚时间
//为什么需要lasttime?
//根据约束条件一,每道工序都要在前一道工序完成后才能开始
/*
  例如题目中的例子,第一个工件的第一道工序已经安排好了,
  在第一台机器上由0到3,那么3就是第一个工件的lasttime,
  因为无论第二道工序在哪台机器上,它的开始时间都不能小于
  lasttime否则违反约束一。
*/

int main(void)
{
	int m = 0, n = 0, answer = 0, order[500] = { 0 };

	//m机器数,n工件数,order为安排顺序,answer存放答案

	infomation info[21][21] = { 0 };

	//二维数组记录每个工件的每道工序
	//横向是工序号,纵向是工件号

	cur pos[21] = { 0 }; 
	bool machine[21][10000] = { 0 };

	//pos数组就是每个工件当前状态
	//machine的bool类型数组用来模拟机器运作
	//这边定义10000是因为题目有点小坑,一个工件的每道工序
	//可以在同一台机器上,题目的说明有问题
	//未被占用的标false,被占用的标true
    //类似题目给的方案一方案二的图

	scanf("%d %d", &m, &n);
	for (int i = 1; i <= m * n; i++)
		scanf("%d", &order[i]);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%d", &info[i][j].number);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%d", &info[i][j].time);

	//正常的读入,要注意读入次序
	//数组都从1开始读入,这样查找的时候方便

	for (int i = 1; i <= m * n; i++)//遍历order数组
	{
		int cop = order[i];
		int rank = ++pos[cop].now;
		int count = 0;

		//cop变量即工件号,rank变量即该工件当前工序
		//用++的原因是pos的初始化值是0,即第0道工序
		//++后变为第一道工序
		//额外定义变量是为了接下来的代码更易读
		//count为计数器,具体作用下面再介绍

		int Number = info[cop][rank].number;
		int Time = info[cop][rank].time;

		//Number变量用来记录当前工件的工序在哪个机器上加工
		//Time变量用来记录该工序花费的时间

		for (int j = pos[cop].lasttime + 1;; j++)
		{
			//j变量用于操作machine数组,假如一工件的上
			//一道工序的lasttime为4,那么j就要从5开始计数
			//因此j=lasttime+1

			if (!machine[Number][j]) count++;
			else count = 0;

			//count用来计算有多少个空位即有多少false
			//count表示了一个空位段的长度
			//如果遇到true则count要直接清空

			if (count >= Time) {
				for (int k = j - count + 1; k <= j; k++)
					machine[Number][k] = true;

				//如果这个空位段长度大于该工序的用时
				//则把该空位段打上标记true,表明该时间段已经被占用

				pos[cop].lasttime = j;//更新lasttime
				count = 0;//count清零,准备下一次计算
				break;//找到后可以跳出循环
			}
		}
	}
	for (int i = 1; i <= n; i++)
		if (pos[i].lasttime > answer)
			answer = pos[i].lasttime;
	//找到pos数组中lasttime的最大值,即为答案
	printf("%d", answer);
	//完结撒花
	return 0;
}

这篇关于P1065 [NOIP2006 提高组] 作业调度方案的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!