纯纯大水题。赛前写来模拟练手感。
看到数据范围这么小我还以为是状压,然后发现题目甚至连操作顺序都给出了,因此直接模拟就是对的。
直接暴力搜一遍插入点就可以,数据甚至小得不需要二分。
哎,看了一眼榜学弟写的都比我短,果然是年龄越小的人写代码越本质。
但是我是最优解。
#include <bits/stdc++.h>
using namespace std;
const int N = 25, M = 415;
const int INF = 0x3f3f3f3f;
int n, m;
int cnt[N], opt[M];
int id[N][N], t[N][N];
int lst[N]; //工件最后一次完成的时间
struct node {
int st, tm;
} a[N][M]; int p[N];
int ans = 0;
int main() {
scanf("%d%d", &m, &n); //m 个机器,n 个工件
for (int i = 1; i <= n * m; i++) scanf("%d", &opt[i]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) scanf("%d", &id[i][j]);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) scanf("%d", &t[i][j]);
for (int i = 1; i <= n * m; i++) {
int u = opt[i]; cnt[u]++; //工件 u,执行到第 cnt[u] 道工序
int x = id[u][cnt[u]], tim = t[u][cnt[u]]; //机器编号 x、执行时间 tim
int pos = 0, start = 0;
a[x][ ++p[x] ] = (node){INF, INF};
for (int j = 0; j <= p[x]; j++) {
if (j == p[x]) { pos = j; break; }
// if (a[x][j].st + a[x][j].tm < lst[u]) continue;
if (a[x][j + 1].st - max( lst[u], (a[x][j].st + a[x][j].tm) ) >= tim) {
start = max(lst[u], a[x][j].st + a[x][j].tm);
pos = j + 1; break;
}
}
if (pos == p[x]) start = max(lst[u], a[x][p[x] - 1].st + a[x][p[x] - 1].tm);
for (int j = p[x]; j > pos; j--) a[x][j] = a[x][j - 1];
a[x][pos] = (node){start, tim};
lst[u] = start + tim;
// for (int j = 1; j <= n; j++) cout << lst[j] << ' '; puts("");
}
for (int i = 1; i <= n; i++) ans = max(ans, lst[i]);
printf("%d\n", ans);
return 0;
}