加工生产调度
Johnson 法则分段排序后模拟求工期
正文
// 原题:https://oj.yecheng.tv/p/T1425
// 题意:n 个产品都要先在 A 车间加工再到 B 车间,给出各产品在两车间的时间,求最短总工期及对应的加工顺序。
// 思路:Johnson 法则。
// 1. A 时间小于 B 时间的产品放前段,按 A 时间升序排。
// 2. 其余产品放后段,按 B 时间降序排。
// 3. 按排好的顺序模拟:累加 A 的完工时刻,B 的开始时刻取「自身在 A 完工」与「上一个在 B 完工」的较大者。
// 复杂度:O(n log n) 时间 / O(n) 空间
// 易错点:后段是按 B 时间降序排,写成升序就得不到最优顺序。
// 易错点:总工期是 B 车间的最后完工时刻,不是 A、B 两个车间时间之和。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
if(!(cin >> n)) return 0;
vector<int> a(n), b(n);
for(int i = 0; i < n; i++) cin >> a[i];
for(int i = 0; i < n; i++) cin >> b[i];
vector<int> front, back;
for(int i = 0; i < n; i++){
if(a[i] < b[i]) front.push_back(i);
else back.push_back(i);
}
sort(front.begin(), front.end(), [&](int x, int y){
return a[x] < a[y];
});
sort(back.begin(), back.end(), [&](int x, int y){
return b[x] > b[y];
});
vector<int> ord;
for(int x : front) ord.push_back(x);
for(int x : back) ord.push_back(x);
long long ta = 0, tb = 0;
for(int x : ord){
ta += a[x];
tb = max(tb, ta) + b[x];
}
cout << tb << "\n";
for(int i = 0; i < n; i++){
if(i) cout << " ";
cout << ord[i] + 1;
}
cout << "\n";
return 0;
}
一本通·提高篇的其它内容
- 活动安排
- 种树
- 喷水装置
- 智力大冲浪
- 数列极差
- 数列分段
- 线段
- 家庭作业
- 钓鱼
- 糖果传递
- 愤怒的牛
- Best Cow Fences
- 曲线
- 数列分段 II
- 扩散
- 灯泡
- 传送带
- 数的划分
- 生日蛋糕
- 小木棍
- Addition Chains
- 埃及分数
- 平板涂色
- 质数方阵
- 靶形数独
- 电路维修
- 魔板
- Knight Moves
- 棋盘游戏
- Keyboarding
- 移动玩具
- 山峰和山谷
- Oulipo
- 图书管理
- Power Strings
- Seekthe Name, Seek the Fame
- Friends
- A Horrible Poem
- Beads
- Antisymmetry
- 门票
- 收集雪花
- 剪花布条
- Power Strings
- Radio Transmission
- OKR-Periods of Words
- 似乎在梦中见过的样子
- Censoring
- Phone List
- The XOR Largest Pair
- Nikitosh 和异或
- Immediate Decodability
- L 语言
- Secret Message 秘密信息
- 背单词
- The Xor-longest Path
- Keywords Search
- 玄武密码
- Censoring
- 单词