加工生产调度

【题目描述】

某工厂收到了n个产品的订单,这n个产品分别在A、B两个车间加工,并且必须先在A车间加工后才可以到B车间加工。

某个产品i在A、B两车间加工的时间分别为Ai、Bi。询问怎样安排这n个产品的加工顺序,才能使总的加工时间最短。这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在A、B两车间加工完毕的时间。

【输入描述】

第一行输入一个整数n(0 < n < 1000),表示产品的数量;

第二行输入n个整数,表示这n个产品在A车间加工各自所要的时间;

第三行输入n个整数,表示这n个产品在B车间加工各自所要的时间。

【输出描述】

输出一个数,表示最少的加工时间。

【样例输入】

5

3 5 8 7 10

6 2 1 4 9

【样例输出】

34

源代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int n,A[1001],B[1001],C[1001],T[1001];
struct Node
{
    int Num,Time;
    bool Flag;
}i[1001];
bool Rule(Node t1,Node t2)
{
    return t1.Time<t2.Time;
}
void Johnson()
{
    for (int a=1;a<=n;a++)
    {
        if (A[a]>B[a])
        {
            i[a].Flag=true;
            i[a].Time=B[a];
        }
        else
        {
            i[a].Flag=false;
            i[a].Time=A[a];
        }
        i[a].Num=a;
    }
    sort(i+1,i+n+1,Rule);
    int Left=0,Right=n+1;
    for (int a=1;a<=n;a++)
      if (i[a].Flag)
        C[--Right]=i[a].Num;
      else
        C[++Left]=i[a].Num;
}
int main()
{
    scanf("%d",&n);
    for (int a=1;a<=n;a++)
      scanf("%d",&A[a]);
    for (int a=1;a<=n;a++)
      scanf("%d",&B[a]);
    Johnson();
    for (int a=1;a<=n;a++)
      T[a]=T[a-1]+A[C[a]];
    int Ans=T[1]+B[C[1]]; //第一段比较特殊。
    for (int a=2;a<=n;a++)
      Ans=max(Ans,T[a])+B[C[a]]; //将连续的A[i]与A[i-1]+B[i-1]作比较。
    printf("%d",Ans);
    return 0;
}

/*
    虽然做出来了,但这Johnson算法求流水作业调度问题依然是云里雾里。
    算法正确性的证明依旧不懂。
    以样例数据为例:
        (A1,A2,A3,A4,A5)=(3,5,8,7,10)
        (B1,B2,B3,B4,B5)=(6,2,1,4,9)
        则最小值集合(M1,M2,M3,M4,M5)=(3,2,1,4,9)
        排序之后为:(M3,M2,M1,M4,M5)
        进行顺序处理:
            M3=B3,所以M3安排在后面( , , , ,3);
            M2=B2,所以M2安排在后面( , , ,2,3);
            M1=A1,所以M1安排在前面(1, , ,2,3);
            M4=B4,所以M4安排在后面(1, ,4,2,3);
            M5=B5,所以M5安排在后面(1,5,4,2,3);
        从而得到加工顺序为:1,5,4,2,3。
        计算出最短的加工时间34。
*/
原文地址:https://www.cnblogs.com/Ackermann/p/5564885.html