算法 | 流水调度问题

问题描述:

 n个作业{1,2,…,n}要在由2台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi。流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。

Johnson法则:一句话概括上方两个特点:尽可能早安排m1上加工时间<在M2上的加工时间的作业

在M1上加工时间短,将其放前边

在M2上加工时间短,将其放后边

于是我们就清楚流水作业调度把加工作业分为两类

  1. 在M1上加工时间<在M2上加工时间,并且按照在M1上加工时间由小到大(递增)排序
  2. 在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
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值