洛谷的模拟绿题
传送门 :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;
}