题目描述
某工厂收到了 n n n 个产品的订单,这 n n n 个产品分别在 A A A、 B B B 两个车间加工,并且必须先在 A A A 车间加工后才可以到 B B B 车间加工。
某个产品 i i i 在 A A A, B B B 两车间加工的时间分别为 A i A_i Ai, B i B_i Bi。怎样安排这 n n n 个产品的加工顺序,才能使总的加工时间最短。
这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A A A, B B B 两车间加工完毕的时间。
输入格式
第一行仅—个数据 n n n ,表示产品的数量;
接下来 n n n 个数据是表示这 n n n 个产品在 A A A 车间加工各自所要的时间;
最后的 n n n 个数据是表示这 n n n 个产品在 B B B 车间加工各自所要的时间。
输出格式
第一行一个数据,表示最少的加工时间;
第二行是一种最小加工时间的加工顺序。
输入样例
5
3 5 8 7 10
6 2 1 4 9
输出样例
34
1 5 4 2 3
数据范围
对于 100 % 100\% 100% 的数据, 0 < n < 10000 0 < n < 10000 0<n<10000,所有数值皆为整数。
解题思路
贪心策略,设 M = m i n { a i , b i } M = min\left\{a_i,b_i\right\} M=min{ai,bi},将 M M M 按照从小到大的顺序排序,然后从第 1 个开始处理,若 M i = a Mi=a Mi=a,则将它排在从头开始的作业后面,若 M i = b M_i=b Mi=b,则将它排在从尾开始的作业前面。
标准程序
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
const int N = 10005;
int n, a[N], b[N], c[N];
struct node {
int type, id, time;
} m[N];
bool cmp(node x, node y) { return x.time < y.time; };
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]); //读入 A 车间加工第 i 个产品的时间
for (int i = 1; i <= n; i++) scanf("%d", &b[i]); //读入 B 车间加工第 i 个产品的时间
//比较ai和bi,选择较小的时间
for (int i = 1; i <= n; i++)
if (a[i] <= b[i])
m[i] = {0, i, a[i]};
else
m[i] = {1, i, b[i]};
//按照加工时间排序
sort(m + 1, m + n + 1, cmp);
//如果第i件物品如果是A车间的,加到开始作业序列最后一个,否则加到结尾序列的第一个。
int l = 0, r = n + 1; //这里用双指针
for (int i = 1; i <= n; i++) {
if (m[i].type == 0)
c[++l] = m[i].id;
else
c[--r] = m[i].id;
}
//模拟整个加工过程,计算总的加工时间。
int k = 0, t = 0;
for (int i = 1; i <= n; i++) {
k += a[c[i]];
if (t < k) t = k; //因为B车间要等A车间加工完才能加工后,才能加工
t += b[c[i]];
}
printf("%d\n", t);
for (int i = 1; i <= n; i++) printf("%d ", c[i]); //输出整个选择的序列
return 0;
}