加工生产调度

题目描述

某工厂收到了 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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值