王晓东的《计算机算法设计与分析》上这一节我看的云里雾里,数学公式让我眼花缭乱。但是读懂数学公式的推导过程并不是最重要的事情。重要的是解题的思路!
-
我读懂了“流水作业”的题目要求,以及最优子结构性质
动态规划——流水作业调度问题 -
这里有流水作业的具体实例,很好地展示了自底向上的动规过程,C++代码
0018算法笔记——【动态规划】流水作业调度问题与Johnson法则 -
Java 代码,注释写的很详细
动态规划之流水作业调度Johnson法则
#include <iostream>
#include <stdlib.h>
using namespace std;
// 动态规划 流水作业调度问题
class Jobtype
{
public:
int operator <=(Jobtype a) const
{
return(key<=a.key);
}
int key,index;
bool job;
};
/*
定义作业Jobtype类:
key : 关键字
index :索引值
bool job : a[i]<=b[i]的归入N1类,job值为1 ; 否则为0
重新定义运算符 <=
*/
int FlowShop(int n,int a[],int b[],int c[]);
void BubbleSort(Jobtype *d,int n);
int FlowShop(int n,int a[],int b[],int c[])
{
Jobtype *d = new Jobtype[n];
for(int i=0; i<n; i++)
{
d[i].key = a[i]>b[i]?b[i]:a[i];//按Johnson法则分别取对应的b[i]或a[i]值作为关键字
d[i].job = a[i]<=b[i];//给符合条件a[i]<b[i]的放入到N1子集标记为true
d[i].index = i;
}
BubbleSort(d,n);//对数组d按关键字升序进行排序
int j = 0,k = n-1;
for(int i=0; i<n; i++)
{
if(d[i].job)
{
c[j++] = d[i].index;//将排过序的数组d,取其中作业序号属于N1的从前面进入
}
else
{
c[k--] = d[i].index;//属于N2的从后面进入,从而实现N1的非减序排序,N2的非增序排序
}
}
j = a[c[0]];
k = j+b[c[0]];
for(int i=1; i<n; i++)
{
j += a[c[i]];//M1在执行c[i]作业的同时,M2在执行c[i-1]号作业,最短执行时间取决于M1与M2谁后执行完
k = j<k?k+b[c[i]]:j+b[c[i]];//计算最优加工时间
}
delete d;
return k;
}
//冒泡排序
void BubbleSort(Jobtype *d,int n)
{
int i,j,flag;
Jobtype temp;
for(i=0;i<n;i++){
flag = 0;
for(j=n-1;j>i;j--){
//如果前一个数大于后一个数,则交换
if(d[j]<=d[j-1]){
temp = d[j];
d[j] = d[j-1];
d[j-1] = temp;
flag = 1;
}
}
//如果本次排序没有进行一次交换,则break,减少了执行之间。
if(flag == 0){
break;
}
}
}
int main()
{
int N; // 作业个数
cout<<"请输入作业总个数n:"<<endl;
cin>>N;
int a[N],b[N],c[N];
cout<<"请输入machine1的作业运行时间:"<<endl;
for (int i=0 ; i<N ;i++)
{
cin >> a[i];
}
cout<<"请输入machine2的作业运行时间:"<<endl;
for (int i=0 ; i<N ;i++)
{
cin >> b[i];
}
int minTime=FlowShop(N,a,b,c);
/*
a[N]:machine1的作业运行时间序列
b[N]:machine2的作业运行时间序列
c[N]:N个作业的调度顺序(编号从0开始)
*/
cout<<"初始作业在机器1上的运行时间序列为:"<<endl;
for(int i=0; i<N; i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
cout<<"初始作业在机器2上的运行时间序列为:"<<endl;
for(int i=0; i<N; i++)
{
cout<<b[i]<<" ";
}
cout<<endl;
cout<<"完成作业的最短时间为:"<<minTime<<endl;
cout<<"编号从0开始,作业调度的顺序为:"<<endl;
for(int i=0; i<N; i++)
{
cout<<c[i]<<" ";
}
cout<<endl;
return 0;
}