编译环境:Dev-C++
用动态规划算法设计独立任务最优调度问题解决方案并实现,并分析算法复杂性。
独立任务最优调度问题描述:
设有n个作业需要在机器M1和M2组成的流水线上加工,每个工件的加工顺序都是先在M1上加工,然后在M2上加工。m1,m2j分别表示工件j在M1,M2上所需的加工时间(1<=j<=n)。应如何在两机器上安排生产,使得第一个工件从在M1上加工开始到最后一个工件在M2上加工完所需的总加工时间最短。
对问题的分析:
流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。直观上,一个最优调度应使机器M1没有空闲时间,且机器M2的空闲时间最少。(在一般情况下,机器M2上会有机器空闲和作业积压两种情况。)
设全部作业的集合为N={1,2,...,n},S⊆N,S是N的一个子集。在一般情况下,机器M1开始加工S中作业时,机器M2还在加工其他作业,要等时间t后才可利用。这种情况下,完成S中作业所需的最短时间记为T(S,t),流水作业调度问题的最优值为T(N,0)。
①如果作业i在M1上加工完毕后,M2是空闲的,则不需要等待,M2直接加工作业i即可。作业i占用M2的时间为bi+0;
②如果作业i在M1上加工完毕后,M2仍然被之前的作业占用,则作业i在M2上需要等待的时间为t-ai。作业i占用M2的时间为bi+(t-ai);
算法描述
流水作业调度问题的Johnson算法,
(1)令
(2)将N1中作业依ai的非减序排序;将N2中作业依bi的非增序排序;
(3)N1中作业接N2中作业构成满足Johnson法则的最优调度。
调试过程及实验结果
(1)编程过程中出现的问题及解决方法:
①不清楚数组空间分配
数组a分n个int,b分n个,c并不是a和b直接合并的数组,而是a和b去重后合并的结果数组,因此c分n个int空间。
②排序的时候忘记了sort的应用,想自己写快排实现,没写出来,然后用sort对进行排序,又忘了c++的operator<( ),在csdn博客中重新对sort和operator<( )学习
sort函数包含在头文件为#include<algorithm>的c++标准库中,有三个参数,分别是起始位置,结束位置和规定,第三个参数不给的情况下,sort从小到大排序;
(2)结果与测试
Input:
作业数量为:4
在机器M1上加工作业所需的时间分别为: 2 5 10 16
在机器M2上加工作业所需的时间分别为:3 8 2 9
Output:
流水作业调度序列为:1 2 4 3
流水作业调度最短完成时间是:26
算法复杂度分析
算法FlowShop的主要计算时间花在对作业集的排序。
因此,在最坏情况下算法所需的计算时间为O(nlogn)。所需的空间为O(n)。
源代码:
#include <bits/stdc++.h>
using namespace std;
class Jobtype{
public: int key;//作业时间
public: int index;//第几个作业
public: bool job;//作业类型
//比较方法重载
public: bool operator < ( Jobtype& j){
return key <=j.key;
}
};
//形参分别为作业数量 在m1上所需时间a 在m2上所需时间b 流水作业调度序列c
int FlowShop(int n, int a[], int b[], int c[]);
int main(){
int n;
printf("作业数量为:");
scanf("%d",&n);
int a[1000], b[1000], c[1000];
printf("在机器M1上加工作业所需的时间分别为:");
for (int i = 0; i < n; i++)
scanf("%d",a+i);
printf("在机器M2上加工作业所需的时间分别为:");
for (int i = 0; i < n; i++)
scanf("%d",b+i);
int t = FlowShop(n, a, b, c);
printf("流水作业调度最短完成时间是:%d\n",t);
return 0;
}
int FlowShop(int n, int a[], int b[], int c[]){
Jobtype* d = (Jobtype*)malloc(sizeof(Jobtype)*n);
for (int i = 0; i < n; i++){
if(a[i] > b[i]){
d[i].key =b[i];
} else{
d[i].key =a[i];
}
d[i].job = a[i] <= b[i];//前后标志 1代表是序列的最前 0代表是序列的最后
d[i].index = i;//表示第几个
}
sort(d, d + n);
int j = 0, k = n - 1;
for (int i = 0; i < n; i++){
if (d[i].job)
c[j++] = d[i].index;//序列前面
else
c[k--] = d[i].index;//序列后面
}
putchar('\n');
printf("流水作业调度序列为:");
for (int i = 0; i < n; i++)
if(i==0) printf("%d",c[i] + 1);
else printf(" %d",c[i] + 1);
putchar('\n');
j = a[c[0]];
k = j + b[c[0]];
for (int i = 1; i < n; i++){
j += a[c[i]];
if(j < k){
k += b[c[i]];
} else{
k = j + b[c[i]];
}
}
free(d);
return k;
}