贪心算法训练(七)——加工生产调度(流水作业调度问题)

1. 问题描述

  某工厂收到了 n 个产品的订单,这 n 个产品分别在 A、B 两个车间加工,并且必须先在 A 车间加工后才可以送到 B 车间。某个产品 i 在 A、B 两车间加工的时间分别为 $A_i$、$B_i$。怎样安排这 n 个产品的加工顺序,才能使总的加工时间最短?这里所说的加工时间是指:从开始加工第一个产品到所有产品都加工完毕的时间。

2. 输入格式

  第一行仅一个数据 n(0 < n< 1000),表示产品的数量

  接下来 n 个数据是表示这 n 个产品在 A 车间加工,各自所需要的时间(都是整数)

  最后的 n 个数据是表示这 n 个产品在 B 车间加工,各自所需要的时间(都是整数)

3. 输出格式

  第一行一个数据,表示最短的加工时间

  第二行是一种用时最短的产品加工率

4. 样例输入

5
3 5 8 7 10
6 2 1 4 9

5. 样例输出

34 
1 5 4 2 3

6. 思路分析

  直观上,最优调度一定让 $M_1$ 没有空闲,$M_2$ 的空闲时间尽量短

  Johnson 算法:设 $N_1$ 为 a < b 的作业集合,$N_2$ 为 a >= b 的作业集合,将 $N_1$ 的作业按 a 非减序排序,$N_2$ 中的作业按照 b 非增序排序,则 $N_1$ 作业接 $N_2$ 构成最优顺序

7. 代码

#include <iostream>

using namespace std;

int num;
int a[1001],b[1001],c[1001],d[1001];

typedef struct DATA Data;

struct DATA
{
    int m[1001];
    bool mark[1001];
};

Data data;

void insertion_sort(int a[],int arr[],int len);

int main()
{
    ios::sync_with_stdio(false);
    cin>>num;
    int i = 1,sum = 0;
    for(;i <= num;i++)
        cin>>a[i];
    for(i = 1;i <= num;i++)
    {
        cin>>b[i];
        data.m[i] = min(a[i],b[i]);
        d[i] = i;
        if(data.m[i] == a[i])
            data.mark[i] = false;
        else
            data.mark[i] = true;
    }
    insertion_sort(d,data.m,num);
    int j = num,k = 1;
    for(i = 1;i <= num;i++)
    {
        if(data.mark[d[i]] == true)
            c[j--] = d[i];
        else
            c[k++] = d[i];
    }
    for(i = 1;i <= num;i++)
        sum += a[c[i]];
    sum += b[c[i-1]];
    cout<<sum<<endl;
    for(i = 1;i <= num;i++)
        cout<<c[i]<<"  ";
    return 0;
}
void insertion_sort(int a[],int arr[],int len)
{
    for(int i=2; i<=len; i++)
    {
        int key=arr[i];
        int key1 = a[i];
        int j;
        for(j=i-1; j>=0 && key<arr[j]; j--)
        {
            arr[j+1] = arr[j];
            a[j+1] = a[j];
        }
        arr[j+1]=key;
        a[j+1] = key1;
    }
}

  

原文地址:https://www.cnblogs.com/NikkiNikita/p/9460452.html