原谅我不会什么高端技巧吧/(ㄒoㄒ)/~~
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int m,n,c[21][21],t[21][21],o[21],a[21][8001]={0},k[21][21],ti=1;
/*
c[i][j]表示第i个零件的第j个工序由第c[i][j]个机器来完成(见输入)
t[i][j]表示第i个零件的第j个工序完成需要t[i][j]的时间(见输入)
o[i]表示第i个零件已经进行到了o[i]个工序
a[i][j]用来模拟题目表格:第i个机器的第j秒时间是否被占用了
k[i][j]表示第i个零件的第j个工序还剩下k[i][j]秒才完成
ti表示当前时间
*/
queue <int> order;//给定的顺序
void input(){
//输入
for(int i=0;i<21;i++)o[i]=1;
scanf("%d%d",&m,&n);
int _;
for(int i=0;i<m*n;i++){
scanf("%d",&_);
order.push(_);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)scanf("%d",&c[i][j]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)scanf("%d",&t[i][j]);
}
}
void output(){
//输出:将剩下的时间中还需要加工的时间最大值加起来就是答案
int extra=0;
for(int i=0;i<=20;i++){
for(int j=0;j<=20;j++){
if(k[i][j])extra=max(extra,k[i][j]);
}
}
printf("%d",ti+extra-1);
}
bool check(int e,int f){
//检查第e个零件在第j个工序前是否都已经完成
for(int i=1;i<f;i++){
if(k[e][i]>0)return false;
}
return true;
}
void work(){
//时间过了一秒…每一个正在加工零件剩余的时间都-1
ti++;
for(int i=1;i<=20;i++){
for(int j=1;j<=20;j++){
if(k[i][j])k[i][j]--;
}
}
}
int main(){
input();
/*
思路:
拿出顺序中的首个零件,判断是否可以加工:
T用于循环每个零件确保同一秒可能有多个零件同时开始加工
如果不可以加工就把这个零件放到末尾
如果可以加工就拿出来加工:
将剩余时间标记,该机器后面的时间都被占用了,并且该零件下一次要做下一个工序了
每次循环后,更新时间
*/
while(!order.empty()){
int T=order.size();
while(T--){ //看是否会有多台机器同时工作
int N=order.front(),machine=c[N][o[N]]; //N是待加工零件、machine是这个零件希望被哪个机器加工
order.pop(); //先把它踢出队列
if(!a[machine][ti]&&check(N,o[N])){ //同时满足:机器这一秒是空闲的并且该零件前面工序已完成
k[N][o[N]]=t[N][o[N]]; //标记该零件剩余完成时间
for(int i=0;i<t[N][o[N]];i++)a[machine][ti+i]=1; //该机器的后面几秒钟都被占用了
o[N]++; //零件可进入下一个工序加工
}else order.push(N); //做不了这个工序,放回
}
work();
}
output();
return 0;
}