流水线作业调度问题——Johnson不等式

背景  加工生产调度

题目描述

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

某个产品 i 在 A、B 两车间加工的时间分别为Ai,Bi。怎样安排这 n 个产品的加工顺序,才能使总的加工时间最短。

这里所说的加工时间是指:从开始加工第一个产品到最后所有的产品都已在 A、B 两车间加工完毕的时间。

分析

对于这个问题,我们的直观想法就是使ai尽可能的短,bi尽可能的长,这样当我们再进行bi的同时a(i+1)就可以开始运作,就可以省去向下面图4的情况第二台已经空出来了,可是我还得等待a(i+1)加工完毕。

下面我们通过一些图片来解析一下这个题意

示例:有3个作业如下图所示

于是共有6种调度安排:

对于方案 4, 请注意,b2结束后并不能立即进行b3的工作,因为题目已经说了要等a3加工结束才能进行b3的加工

其中方案3总时间最短。

现在我们来分析一下最差方案,对于方案4,使其成为最差的主要原因是因为出现了等待的时间,a3加工时间实在是太长了,但是我们必须等他结束了才能进行b3。然后我们对其进行优化,是否调换一下前后1,2两个作业或者2,3两个作业的先后顺序就可以缩短时间呢。

于是我们引出了关键思路 如果对换“相邻”的两个作业会不会缩短时间?如果能我们就对换

假定 t0+\Delta(t0表示前面加工需要的时间)后 M2 才开始空闲,但作业1在机器2的实际开始时刻应该是 t0+max(\Delta,a1)。因为我们必须等a1加工完毕了我们才能进行b1的加工,也就是说当\Delta<a1的时候会出现空格时间,如上图4,\Delta=b2,实际运行开始运行时间为t0+a3

对作业1之后的作业2而言,有四种情况

 我们分析一下在第二台机器上的加工时间,首先b2是不可能超过a2的,所以我们可以直接加上b2,然后只需考虑前面,由上图便可得到以下等式

  • 在 M1 上的最早开始时间是t0+a1+a2
  • 在 M2 上的最早开始时间是 T1=t0+max\left \{ a1+a2,a1+b1,\Delta+b1 \right \}+b2
  • 使用我们总的加工时间就是T1

当作业1和作业2的次序对换时, Δ 不变化,此时对作业2之后的作业而言:

  • 在 M1 上的最早开始时间是t0+a1+a2;(没有变化)
  • 在 M2 上的最早开始时间是 T2=t0+max\left \{ a2+a1,a2+b2,\Delta+b2 \right \}+b1
  • 使用我们总的加工时间就是T2

 下面我们分四种情况讨论一下交换前和交换后,这两个作业在 M2 上都完成的最早时间:

首先我们记a1=min \left \{ a1,a2,b1,b2\right \}表示的是a1,a2,b1,b2之间的最小值是a1

a1=min \left \{ a1,a2,b1,b2\right \} 。此时有 a1+a2\leqslant b2+a2

于是T2=t0+max\left \{a2+b2,\Delta+b2 \right \}+b1      (求的是最大值,所以可以直接把小的去掉)  

T2=t0+max\left \{a2+b1,\Delta+b1\right \}+b2         求出的最大值都是+b1+b2的,所以换序无妨

a2+a1\leqslant a2+b1, a1+b1\leqslant a2+b1 (这里说简单点就是a1<b1,a1<a2)

可得T1=t0+max\left \{a2+b1,a1+b1,\Delta+b1 \right \}+b2\leqslant t0+max\left \{a2+b1,\Delta+b1\right \}+b2=T2

因此 T1<T2,即交换次序不会使情况变好

 a2=min \left \{ a1,a2,b1,b2\right \}。类似于①,自证,可知T1\geqslant T2 ,即交换次序不会是其变差

                (取得到等号所以不能直接说变好)

 b1=min \left \{ a1,a2,b1,b2\right \} 。 此时有 a1+a2\geqslant a1+b1

于是T1=t0+max\left \{ a1+a2,\Delta+b1 \right \}+b2=t0+max\left \{ a1+a2+b2,\Delta+b1+b2 \right \}

又 a1+a2+b2\geqslant a1+a2+b1 , a1+a2+b2\geq a1+a2+b1 

可得T1=t0+max\left \{ a1+a2+b2,\Delta+b1+b2 \right \}\geqslant max\left \{ a2+a1+b1,a2+b2+b1,\Delta +b2+b1\right \}=T2

T1>T2,即交换次序不会使情况变差

④ b2=min \left \{ a1,a2,b1,b2\right \} 。类似③,可得,即交换次序不会使情况变好

以上分析了什么情况下对换“相邻”的两个作业至少不会使情况变差

因此我们可以从局部到整体,分析如何确定加工顺序。

计算 min\left \{ a1,b1,a1,b1,...an,bn \right \} ,有两种情况:

 这个最小值是某个ai,那么如果它不是第一个被加工的,就可以根据②将它与前面相邻的任务次序对换,而总时间不会变长(还有可能变短)。不断这样进行下去,直到它成为第一个被加工的。把它放到该放的位置,以后就不用考虑它了。

  这个最小值是某个 bj ,那么如果它不是最后一个被加工的,就可以根据③将它与后面相邻的任务次序对换,而总时间不会变长(还有可能变短)。不断这样进行下去,直到它成为最后一个被加工的。把它放到该放的位置,以后就不用考虑它了。

而②和③,就是所称的“Johnson不等式”:

如果作业 i 和 j ,i在j前面,满足 min\left \{ bi,aj \right \}\geqslant min\left \{ bi,aj \right \},则称作业 i 和 j 满足Johnson不等式。

代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1005;
int n,ans;

struct node
{
	int a,b,c;//分别代表作业1和作业2,还有对应编号,
               //i表示不了,因为后面要排序我们先记录一下
	bool operator<(const node &v)
	{
		return min(a,v.b)<min(b,v.a);//Johnson不等式,注意小于号左边的是前一个的b作业与后一个 
                                      的a作业
	}
}d[N];

int main()
{
	int n;cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>d[i].a;d[i].c=i;
	}
	for(int i=1;i<=n;i++)
		cin>>d[i].b;
	
	sort(d+1,d+1+n);

	int x=0,y=0;
	for(int i=1;i<=n;i++)
	{
		x+=d[i].a;
		y=max(x,y)+d[i].b;//首先无论如何都需要等到ai结束才能进行bi,
                          //其次如果ai结束了bi-1,还没结束我们依然要等,所以取其中最大值
	}
	cout<<y<<"\n";
	for(int i=1;i<=n;i++)
		cout<<d[i].c<<" ";
	return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值