问题描述:
n个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi。流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。
Johnson法则:一句话概括上方两个特点:尽可能早安排在m1上加工时间<在M2上的加工时间的作业
在M1上加工时间短,将其放前边
在M2上加工时间短,将其放后边
于是我们就清楚流水作业调度把加工作业分为两类
- 在M1上加工时间<在M2上加工时间,并且按照在M1上加工时间由小到大(递增)排序
- 在M1上加工时间>=在M2上加工时间,并且按照在M2上加工时间由大到小(递减)排序
第一类作业接第二类作业构成的顺序满足johnson法则的最优调度。
这里给出一个例子帮助更好的理解:
流水作业调度求解实例
求最佳作业安排次序及时间
①把作业分成两类
N1={J1,J3,J4}--------------在M1上加工时间<在M2上加工时间
N1={J4,J1,J3}--------------按照在M1上加工时间由小到大(递增)排序
N2={J2,J5,J6}--------------在M1上加工时间>在M2上加工时间
N2={J2,J5,J6}--------------按照在M2上加工时间由大到小(递减)排序
②得到最优序列
N1接N2构成满足JOHNSON法则的最优序列:J4,J1,J3,J2,J5,J6
③作业在M1和M2上的结束时间表
因此总的加工时间为430。
代码:
```cpp
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 100
using namespace std;
struct node {
int time;//执行时间
int index;//作业序号
bool group;//1代表第一个机器,0代表第二个机器
};
bool cmp(node a,node b)
{//升序排序
return a.time<b.time;
}
int main()
{
int i,j,k,n;
int M1[N]={0},M2[N]={0};
int best[N];//最优调度序列
node c[N];
printf("请输入作业的个数(<100)\n");
scanf("%d",&n);
printf("请分别输入每个作业在M1与M2上的作业时间:(以空格分隔,eg:30 80)\n");
for(i=0;i<n;i++) {
scanf("%d%d",&M1[i],&M2[i]);
}
for(i=0;i<n;i++) { //把n个作业分成两组
c[i].time=M1[i]>M2[i]?M2[i]:M1[i];
c[i].index=i;
c[i].group=M1[i]<=M2[i];
}
//验证输出
printf("\n\n");
for(i=0;i<n;i++)
{
printf("%d %d %d\n",c[i].time,c[i].index,c[i].group);
}
sort(c,c+n,cmp);//按照c[]中作业时间增序排序
//验证输出
printf("\n\n");
for(i=0;i<n;i++)
{
printf("%d %d %d\n",c[i].time,c[i].index,c[i].group);
}
j=0,k=n-1;
for(i=0;i<n;i++) {
if(c[i].group) { //M1.从i=0开始放入到best[]中
best[j++]=c[i].index;
}
else {
best[k--]=c[i].index;//M2,倒着来
}
}
j=M1[best[0]];//初始化,M1最优调度序列下的作业结束时间
k=j+M2[best[0]];//初始化,M2最优调度序列下的作业结束时间
for(i=1;i<n;i++) {
j+=M1[best[i]];//下一个作业在M1上的结束时间
if(j<k)//计算下一个作业在M2上的结束时间,如果j<k表明本作业在M1结束时间小于上一个作业的M2结束时间,就说这个作业在30完成了M1的工作,上一个作业在50完成M2的工作,就是说你得等,M2不空闲,这是好的情况
{
k=k+M2[best[i]];//那么本作业在M2上的结束时间就是上一个作业在M2上的结束时间加上我这个作业在M2上的运行时间
}else{
k=j+M2[best[i]];//否则的话,就说明想要M2的时候,M2正好空着,那就在M1上的结束时间加上M2上的运行时间
}
// k=j<k?(k+M2[best[i]]):j+M2[best[i]];//消耗总时间的最大值
}
printf("本次运行总时间为:\n");
printf("%d\n",k);
printf("最优调度序列为:\n");
for(i=0;i<n;i++) {
printf("%d ",best[i]+1);
}
printf("\n");
return 0;
}
/*
测试样例
6
30 80
120 100
50 90
20 60
90 30
110 10
*/