Files
python/TangDou/LuoGuBook/P1065_2.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

93 lines
4.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 20 + 10; //m<20,n<20,范围是20以内,开大一点防止出错
//题意解析
//https://www.bilibili.com/video/BV14K411J7Hr?from=search&seid=5350204733209198842
//手绘图形进行样例解析说明,让学生们手工绘制帮助理解题意。
//用来记录题目输入的数据信息
int n, m; //m表示机器数,n表示工件数
int seq[N * N]; //为给定的安排顺序。大小为m*n,所以开了一个N*N的数组。是安排顺序的简写形式。
//举个例子: 112332 表示第一个工件第一道工序,第一个工件第二道工序,第二个工件第1个工序....
int p[N][N]; //工件+工序的机器号
int t[N][N]; //工件+工序的执行时长
//下面是程序开发中需要的中间变量
int cnt[N]; //用来存储遍历到了当前工件的第几个工序
//Q:为什么要用数组来存储是第几个工序?
//A:因为有多个工件,每一个工件都随时需要知道它现在再次出现的是第几个工序了,需要有地方可以查询到,这里使用了桶排的思想。
int last[N]; //记录每份工件的最后一次加工时间
//Q:为什么要记录最后一次的加工时间?
//A:因为每个工件,它的加工顺序是不能反的,也就是规则1,如何才能不违反规则1呢?就是记录下它的最后一次执行时间,然后把下一个工序安排在最后一次执行时间后面就行了。
int res[N][N * N * 100]; //标识每台机器的时间使用情况,第一维:机器,第二维:时间,值:是不是占用了
/**
* 功能:检查函数
* @param start 从哪个时间开始
* @param len 需要多长的时间
* @param mac 哪台机器上进行检查
* @return 是不是能放得下去
*/
bool check(int start, int len, int mac) {
for (int i = start; i < start + len; i++)
if (res[mac][i])return false; //在这个范围内,如果有使用的情况,就返回false, 表示放不下去
//全部通过,表示可以放的下去,返回true
return true;
}
int main() {
//m机器数,n工件数
//示例数据:2 3,表示2台机器,3个工件
cin >> m >> n;
//给定的安排顺序,示例数据:1 1 2 3 3 2,描述第一个物品第一个工序,第一个物品第二个工序,第二个物品第一个工序,第三个物品第一个工序,第三个物品第二个工序,第二个物品第二个工序
for (int i = 1; i <= n * m; i++) cin >> seq[i];
/**
前n行依次表示每个工件的每个工序所使用的机器号,第1个数为第1个工序的机器号,第2个数为第2个工序机器号,等等。
1 2 第一件物品,第1个工序需要在1号机器上进行,第2个工序需要在2号机器上进行
1 2 第二件物品,第1个工序需要在1号机器上进行,第2个工序需要在2号机器上进行
2 1 第三件物品,第1个工序需要在2号机器上进行,第2个工序需要在1号机器上进行
*/
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> p[i][j];
//每个工件的每个工序的加工时间
//后n行依次表示每个工件的每个工序的加工时间。
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
cin >> t[i][j];
//找到最长的时间是哪个
int ans = 0;
//处理每一个输入顺序
for (int i = 1; i <= n * m; i++) {
//利用桶排思路,记录每个工件的加工到第几个工序
cnt[seq[i]]++;
int x = seq[i]; //第几个工件
int y = cnt[seq[i]]; //此工件的第几个工序(第几次出现)
int mac = p[x][y]; //根据工件+工件的工序--->第几个机器上加工
for (int j = last[x];; j++) { //此工件需要在最后一次加工时间的基础上去尝试,符合规则1,直到找到答案为止
//看看有空的话,能不能放的下去,比如有3个空,但不够长,就不行
if (check(j, t[x][y], mac)) {
//标识此位置被占用
for (int k = j; k < j + t[x][y]; k++)res[mac][k] = x;
//更新最后的位置值
last[x] = j + t[x][y];
//不断的更新最大值
ans = max(ans, last[x]);
break;
}
}
}
cout << ans << endl;
return 0;
}