分枝限界法求解流水线作业调度问题
问题描述
有n个作业(编号为1~n)要在由两台机器M1和M2组成的流水线上完成加工。每个作业加工的顺序都是先在M1上加工,然后在M2上加工。M1和M2加工作业i所需的时间分别为ai和bi(1≤i≤n)。
流水作业调度问题要求确定这n个作业的最优加工顺序,使得从第一个作业在机器M1上开始加工,到最后一个作业在机器M2上加工完成所需的时间最少。可以假定任何作业一旦开始加工,就不允许被中断,直到该作业被完成,即非优先调度。
问题求解
作业编号为1到n,调度方案的执行步骤为1到n,解空间每一层对应一个步骤的作业分配。
根结点对应步骤0(虚),依次为步骤1、2、…、n分配任务,叶子结点对应步骤n。
叶子节点为一个可行解,比较求最优解
对于按1~n顺序执行的某种调度方案,f1表示在M1上执行完当前第i步的作业对应的总时间,f2数组表示在M2上执行完当前第i步的作业的总时间。
若第i步执行作业j,计算公式如下:
f1=f1+a[j];
f2[i]=max(f1,f2[i-1])+b[j]
这里由于每个结点中都保存了f1和f2,因此可以将f2数组改为单个变量。将每个队列结点的类型声明如下:
struct NodeType //队列结点类型
{ int no; //结点编号int x[MAX]; //x[i]表示第i步分配作业编号int y[MAX]; //y[i]=1表示编号为i的作业已经分配int i; //步骤编号int f1; //已经分配作业M1的执行时间int f2; //已经分配作业M2的执行时间int lb; //下界bool operator<(const NodeType &s) const //重载<关系函数{return lb>s.lb; //lb越小越优先出队}
};
对应的求结点e的lb的算法如下:
void bound(NodeType &e) //求结点e的限界值
{ int sum=0;for (int i=1;i<=n;i++) //扫描所有作业if (e.y[i]==0) sum+=b[i];//仅累计e.x中还没有分配的作业的b时间e.lb=e.f2+sum;
}
用bestf(初始值为∞)存放最优调度时间。
bestx数组存放当前作业最优调度。
采用的剪枝原则是,仅仅扩展 e.lb<bestf 的结点。
代码
//问题表示
int n=4; //作业数
int a[MAX]={0,5,12,4,8}; //M1上的执行时间,不用下标0的元素
int b[MAX]={0,6,2,14,7}; //M2上的执行时间,不用下标0的元素
//求解结果表示
int bestf=INF; //存放最优调度时间
int bestx[MAX]; //存放当前作业最佳调度
int total=1; //结点个数累计struct NodeType //队列结点类型
{ int no; //结点编号int x[MAX]; //x[i]表示第i步分配作业编号int y[MAX]; //y[i]=1表示编号为i的作业已经分配int i; //步骤编号int f1; //已经分配作业M1的执行时间int f2; //已经分配作业M2的执行时间int lb; //下界bool operator<(const NodeType &s) const //重载<关系函数{return lb>s.lb; //lb越小越优先出队}
};void bound(NodeType &e)
{int sum=0;for(int i=1;i<=n;i++)if(e.y[i]==0)//当前作业未被分配sum+=b[i];e.lb=e.f2+sum;
}void bfs()
{NodeType e,e1;priority_queue<NodeType> qu;memset(e.x,0,sizeof(e.x));messet(e.y,0,sizeof(e.y));e.i=0;e.f1=0;e.f2=0;bound(e);e.no=total++;qu.push(e);while(!qu.empty()){e=qu.top();qu.pop();if(e.i==n){if(e.f2<bestf){bestf=e.f2;for(int j=1;j<=n;j++)bestx[j]=e.x[j];}}e1.i=e.i+1;for(int j=1;j<=n;j++){if(e.y[j]==1)continue;for(int i=1;i<=n;i++)e1.x[i]=e.x[i];e1.x[e1.i]=j;for(int i=1;i<=n;i++)e1.y[i]=e.y[i];e1.y[j]=1;e1.f1=e.f1+a[j];e1.f2=max(e1.f1,e.f2)+b[j];bound(e1);if(e1.lb<bestf){e1.no=total++;qu.push(e1);}}}
}
改进
在扩展每个子结点时判断是否为叶子结点,若是则产生一个可行解,比较产生最优解,该叶子结点不进队;若不是叶子结点则将其进队。
//问题表示
int n=4; //作业数
int a[MAX]={0,5,12,4,8}; //M1上的执行时间,不用下标0的元素
int b[MAX]={0,6,2,14,7}; //M2上的执行时间,不用下标0的元素
//求解结果表示
int bestf=INF; //存放最优调度时间
int bestx[MAX]; //存放当前作业最佳调度
int total=1; //结点个数累计struct NodeType //队列结点类型
{ int no; //结点编号int x[MAX]; //x[i]表示第i步分配作业编号int y[MAX]; //y[i]=1表示编号为i的作业已经分配int i; //步骤编号int f1; //已经分配作业M1的执行时间int f2; //已经分配作业M2的执行时间int lb; //下界bool operator<(const NodeType &s) const //重载<关系函数{return lb>s.lb; //lb越小越优先出队}
};void bound(NodeType &e)
{int sum=0;for(int i=1;i<=n;i++)if(e.y[i]==0)//当前作业未被分配sum+=b[i];e.lb=e.f2+sum;
}void bfs()
{NodeType e,e1;priority_queue<NodeType> qu;memset(e.x,0,sizeof(e.x));messet(e.y,0,sizeof(e.y));e.i=0;e.f1=0;e.f2=0;bound(e);e.no=total++;qu.push(e);while(!qu.empty()){e=qu.top();qu.pop();e1.i=e.i+1;for(int j=1;j<=n;j++){if(e.y[j]==1)continue;for(int i=1;i<=n;i++)e1.x[i]=e.x[i];e1.x[e1.i]=j;for(int i=1;i<=n;i++)e1.y[i]=e.y[i];e1.y[j]=1;e1.f1=e.f1+a[j];e1.f2=max(e1.f1,e.f2)+b[j];bound(e1);if(e1.i==n)//到达叶子节点{if(e1.f2<bestf){bestf=e1.f2;for(int j=1;j<=n;j++)bestx[j]=e1.x[j];}}else if(e1.lb<bestf){e1.no=total++;qu.push(e1);}}}
}
分枝限界法求解流水线作业调度问题相关推荐
- 分枝限界法求解0/1背包问题
问题描述 有n个重量分别为{w1,w2,-,wn}的物品,它们的价值分别为{v1,v2,-,vn},给定一个容量为W的背包. 设计从这些物品中选取一部分物品放入该背包的方案,每个物品要么选中要么不选中 ...
- 分枝限界法求解任务分配问题
问题描述 有n(n≥1)个任务需要分配给n个人执行,每个任务只能分配给一个人,每个人只能执行一个任务. 第i个人执行第j个任务的成本是c[i][j](1≤i,j≤n).求出总成本最小的分配方案. 问题 ...
- 第六章——分枝限界法
分枝限界法概述 分枝限界法和回溯法一样,也是一种在问题的解空间树上搜可行解的穷举算法. 其中"分枝"指的是"分枝限界法"搜索可行解采用的策略为广度优先搜索或实现 ...
- 趣学算法之分枝限界法
14天阅读挑战赛 算法知识点 采用广度优先产生状态空间树的结点,并使用剪枝函数的方法称为--分枝限界法. 分枝限界法的基本做法是: 以广度优先的方式搜索问题的状态空间树.每一个活结点只有一次机会成为扩 ...
- 通过例子讲解回溯法、分枝限界法
1.写在前面 这学期上算法课,对分枝限界法这一章听的似懂非懂.后来复习备考时,参考了王晓东老师的<计算机算法设计与分析>,把这部分的原理彻底整明白了,在此与大家分析心得.我将结合自己的理解 ...
- 南邮《算法分析与设计》期末复习 CH9:分枝限界法
一.分枝限界法 分枝限界法广度优先搜索问题的状态空间树,用剪枝函数(往往是限界函数)进行剪枝,通常求问题的最优解. 二.分枝限界法与回溯法的共同点 都是在问题的状态空间树上搜索问题解的算法,都通过活结 ...
- fifo算法_【算法学习】分枝限界法
分枝限界 关注那些不断已被他人成功应用的新思路.你的原创思想只应该应用在那些你正在研究的问题上. --托马斯·爱迪生(1847-1931) 这周到来的太快, 没想到这么快就迎来了考试. 干了这碗烤柿粥 ...
- 分枝限界法/普通队列 01背包问题
问题 三个物品他们的编号,重量和价值如下.1个背包能够称重30公斤,求装入的物品的最大价值 编号 重量 价值 1 16 45 2 15 25 3 15 25 总结 广度优先搜索解空间树:结点是状态,分 ...
- 回溯法解决批处理作业调度问题
唉,这是作为一个失败的开端.但是,我不害怕失败的!今天稍微晚点睡觉,因为中午多睡啦~最近被王晓东老师的<计算机算法设计与分析>(第4版)折磨得够呛.不会说些文雅的话,这的确是事实.基础差, ...
最新文章
- angularjs-ngModel 控制页面的宽度
- 人群密度估计--Learning to Count with CNN Boosting
- 有限域f9的特征是多少_宽频域谐波的潜在威胁欠缺全面考虑,现有标准需进一步优化...
- 记录使用Spartan-6 FPGA进行一次3-8译码器实验
- 步骤4 - 微服务提供者接收请求,提供服务并传回给Orchestra
- angular面试题及答案_关于最流行的Angular问题的StackOverflow上的48个答案
- Java JDBC篇4——数据库连接池
- C++ 将数据转为字符串的几种方法
- 关于水晶报表打包的一些注意的地方!
- [转载]taking photos with live image preview
- 计算机桌面小工具软件,win10桌面小工具(Desktop Gadgets Installer)
- 《计算机组成与设计(硬件/软件接口)》读书笔记
- NLP之人机对话系统
- vscode中vue代码格式化的相关配置
- ElementUI折叠组件bug问题及解决
- 试试kaggle竞赛:辨别猫狗
- 中大计算机专业在上升中,考研趣事:中科大软件学院400分以上300+,中大计算机321分排第三...
- 魔兽显血改建工具的制作及源码
- 更新内核,显卡驱动崩掉解决办法
- Unity3D 大型游戏 最后一站 源码 部分重点匹配战斗(四)(13)