4.6 独立作业最优调度问题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
4.6 独立作业最优调度问题
算法设计思想:
(1) 动态规划法
用数组*A 和*B 分别存放作业由处理机A 和B 处理需要的时间,预处理得到所有作业均由机器A 处理所需的时间A_total 和均由B 处理的时间B_total 。
构造布尔型三维数组***p ,p[i][j][k]=true 表示前k 个作业能够在机器A 用时不超过i 时间、机器B 不超过j 时间内完成。这样,对于任意一个状态p[i][j][k]=true ,第k 个任务可能由机器A 或机器B 完成,对应的前一状态分别为p[i-A[k-1]][j][k-1]和p[i][j-B[k-1]][k-1]。显然,对任意的i 、j ,有p[i][j][0]。
初始令p[i][j][k]=false ,可以得到动态规划的状态转移方程:
[][][][[1]][][1]|[][[1]][1],0_,0_,1[][][0],0_,0_p i j k p i A k j k p i j B k k i A total j B total k n p i j true i A total j B total
=------≤≤≤≤≤≤⎧⎨
=≤≤≤≤⎩ 计算出所有的状态后,得到最优解(最短处理时间)为:
0_,0_,[][][]=
min {max(,)}i A total j B total p i j n true
minimum i j ≤≤≤≤=
另外,构造整型三维数组***c ,表示p[i][j][k]=true 时第k 个作业的调度情况。初始c[i][j][k]均为0,c[i][j][k]=1表示由机器A 处理,c[i][j][k]=2表示由机器B 处理,c[i][j][k]=3表示机器A 、B 都能处理。在计算状态时,如果p[i-A[k-1]][j][k-1]=true ,则c[i][j][k]=1;如果p[i][j-B[k-1]][k-1]=true ,则c[i][j][k]=2;如果都都满足,则c[i][j][k]=3。从每一个p[i][j][n]=true 且max(i,j)=minimun 的c[i][j][n]反推,即可构造所有可能的最优调度方案。
(2) 二叉树思想输出
二叉树思想输出所有最优解:如果不存在c[i][j][k]=3的情况,则反推c[i][j][n]即可得到所有可能的最优调度方案。但是,解空间中c[i][j][k]=3实际上是二叉树中含有两个儿子的情况,因此必须采用二叉树的遍历算法,才能不漏掉所有的最优方案。想到上学期的数据结构这门课中学到的二叉树结构,通过二叉树的后序遍历算法,即可输出所需叶子节点的路径。
采用动态数组,注意了三维动态数组的申请和释放,这样做节省了内存,使程序变得灵活,可以处理大规模数据。
除此之外,程序对鲁棒性做了增强,对非法输入和文件错误进行了检测。
程序设计代码:
/*头文件 作业调度问题.h*/
#ifndef KNAP_H #define KNAP_H
#include
#include
using namespace std;
struct state //记录状态地址
{
int i, j; //AB处理时间
int k; //处理的任务
int c; //1代表A处理,2代表B处理};
class Schedule //作业调度
{
public:
Schedule(char *in, char *out); //构造函数
~Schedule(); //析构函数
void Solve(); //输出结果到文件protected:
void Plan(); //动态规划最优方案
int Max(int x, int y); //返回二者最大值
void Print(); //打印最优解
void PrintBinaryTree(int i, int j); //用二叉树思想后序遍历打印所有最优方案private:
int task_num; //作业数
int *A, *B; //处理时间数组
int A_total, B_total; //作业均有A/B处理需要时间bool ***p; //p[i][j][k]=true表示前k个作业在A用时不超过i,B不超过j内完成int ***c; //c[i][j][k]表示p[i][j][k]=true时第k个作业的调度情况
int minimum; //最短处理时间
ofstream fout; //输出结果文件
};
#endif
/*函数实现文件作业调度问题.cpp*/
#include "作业调度问题.h"
Schedule::Schedule(char *in, char *out) : fout(out)
{
ifstream fin(in);
if( !fin )
{
fout << "文件" << in << "无法打开!" << endl;
exit(1);
}
fin >> task_num; //初始化作业数
A = new int[task_num];
B = new int[task_num];
for(int i = 0; i < task_num; i++)
fin >> A[i]; //初始化A处理器时间表for(int i = 0; i < task_num; i++)
fin >> B[i]; //初始化B处理器时间表minimum = INT_MAX; //初始化最短处理时间A_total = B_total = 0;
for(int i = 0; i < task_num; i++) //全部由A/B处理的时间{
A_total += A[i];
B_total += B[i];
}
p = new bool**[A_total+1];
c = new int**[A_total+1];
for(int i = 0; i <= A_total; i++)
{
p[i] = new bool*[B_total+1];
c[i] = new int*[B_total+1];
}
for(int i = 0; i <= A_total; i++)
for(int j = 0; j <= B_total; j++)
{
p[i][j] = new bool[task_num+1];
c[i][j] = new int[task_num+1];
for(int k = 0; k <= task_num; k++)
{
p[i][j][k] = false;
c[i][j][k] = 0;
}
}
fin.close();
if( !fout )
{
fout << "文件" << out << "无法打开!" << endl;
exit(1);
}
}
Schedule::~Schedule()