批处理作业调度【回溯算法】
问题描述
给定n个作业的集合 J=(J1J_1J1,J2J_2J2,……,JnJ_nJn)。每个作业JiJ_iJi都有两项任务分别在两台机器上完成。每个作业必须先由机器1处理,再由机器2处理。作业JiJ_iJi需要机器j的处理时间为tijt_{ij}tij(i=1,2,……,n;j=1,2)。对于一个确定的作业调度,设FjiF_{ji}Fji是作业i在机器j上完成处理的时间,则所有作业在机器2上完成处理的时间和f = ∑i=1nF2i\sum_{i=1}^{n}{F_{2i}}∑i=1nF2i称为该作业调度的完成时间和。可以证明,当作业以相同次序在机器1和机器2上完成处理时,可以得到一种最佳调度,即使该作业调度的完成时间和最小。(证明略)
问题解读
- 对于给定的n个作业,指定最佳作业调度方案,使其完成时间和最小,因此是求一个最优值。
- 调度必须遵循:
① 一个作业必须先由机器1处理,再由机器2处理,顺序不可颠倒;
② 机器1处理n个作业的顺序必须和机器2处理n个作业的顺序相同(因为只有这样才能使作业调度的完成时间和最小)。 - 由于是一种作业调度顺序的方案,因此该问题的解空间树是排列树。
实例分析
如下图,给出了3个作业分别需要机器1和机器2的处理时间,试给出一种调度方案,使该作业调度的完成时间和最小。
解:3个作业可能的调度顺序有6种:1→2→3、1→3→2、2→1→3、2→3→1、3→1→2、3→2→1。经过计算,它们的完成时间和对应为:19、18、20、21、19、19,因此最佳调度方案为1→3→2,其完成时间和为18。
解析:现在就来分析一下完成时间和怎样计算(以1→3→2调度为例)
假设是从零点开始的:
- 作业1先在机器1上处理,处理完后紧接着在机器2上处理。对应红线部分,这时作业1在机器2上完成处理的时间为2,F21F{21}F21=3;
- 作业2 需要在机器1上完成的任务可以紧接着作业1在机器1上处理,但需要在机器2上完成的任务就要看作业2在机器1上完成处理的时间晚,还是作业1在机器2上完成处理的时间晚。如图,显然作业2 需要在机器1上完成的任务完成的时间较晚,因此作业2需要在机器1上完成后才能在机器2上继续完成。作业2的处理对应蓝线部分,这时作业2在机器2上完成处理的时间为2,F22F{22}F22=7;
- 同作业2的处理情况,作业3 需要在机器1上完成的任务可以紧接着作业2在机器1上处理,但 需要在机器2上完成的任务就要看作业3在机器1上完成处理的时间晚,还是作业2在机器2上完成处理的时间晚。如图,显然作业3 需要在机器1上完成的任务与需要在机器2上完成的任务的完成时间相同,因此作业3在机器1上完成后可以紧接着在机器2上处理。作业3的处理对应绿线部分,这时作业3在机器2上完成处理的时间为2,F23F{23}F23=8;
综上,作业在机器2上完成处理的时间和为:f = ∑i=13F2i\sum_{i=1}^{3}{F_{2i}}∑i=13F2i = F21F{21}F21+F22F{22}F22+F23F{23}F23 = 18。
注意:这里要强调的是应该如何判断某个作业需要在机器2上完成的任务何时开始,这个节点是上一个作业在机器2上完成处理的时间和本作业在机器1上完成处理的时间的较大者,具体原因已经在解析中详解,这里不再做赘述。
代码实现
#include <iostream>
using namespace std;int n; //作业数
int M[100][100]; //M[i][j]表示第i个作业在机器j上需要处理的时间
int x[100]; //x[i]表示第i个处理的作业为x[i]
int bestx[100]; //x[i]的最优值
int f1; //作业在机器1上完成处理的时间
int f2[100]; //f2[i]表示第i个作业在机器2上完成处理的时间
int f; //用于记录前i个作业在机器2上完成处理的时间和
int bestf; //f的最优值void Swap(int &a,int &b) //交换函数
{int temp;temp=a;a=b;b=temp;
}void Backtrack(int i)
{if(i>n) //每到达一个叶子结点,一定是产生了一个最优解,因此要更新之前最优解的值{if(f<bestf) //更新最优解{for(int j=1;j<=n;j++)bestx[j]=x[j];bestf=f;}}else{for(int j=i;j<=n;j++) //控制展开i-1层结点的各个分支。例如当i=1时,表示在整棵排列树的根结点处,刚要开始探索结点,这时可以展开的分支有1、2、3……{f1+=M[x[j]][1]; //计算第i层(个)作业在机器1上的完成处理的时间if(f2[i-1]>f1) //如果第(i-1)个作业在机器2上的完成处理的时间大于第i个作业在机器1上的完成处理的时间,那么第i个作业想进入机器2,就要等第(i-1)个作业在机器2上完成后再说f2[i]=f2[i-1]+M[x[j]][2];else //否则,第i个作业可以在机器1上完成处理后直接进入机器2。f2[i]=f1+M[x[j]][2];f+=f2[i]; //计算完第i个作业在机器2上的完成处理的时间,就可以计算出前i个作业在机器2上完成处理的时间和了if(f<bestf) //截止到这,已经得到一个前i个作业在机器2上完成处理的时间和f,如果f比之前记录的前i个作业在机器2上的完成处理的时间和的最优值bestf都要小,就可以生成第i层结点的孩子结点,继续探索下一层{Swap(x[i],x[j]); //把处于同一层的并且使f更小的那个结点拿过来,放到正在探索的这个结点处(这里结合排列数的图可以更好地理解)Backtrack(i+1); //继续探索以第i层结点为根结点的子树Swap(x[i],x[j]); //探索完要回溯时,只要做探索前的反“动作”就可以了}f-=f2[i]; //探索完要回溯时,只要做探索前的反“动作”就可以了f1-=M[x[j]][1]; //探索完要回溯时,只要做探索前的反“动作”就可以了}}
}void inPut() //输入函数
{cout<<"请输入作业的个数n:"<<endl;cin>>n;cout<<"请分别输入n个作业在机器1和机器2上各自需要处理的时间(分两行):"<<endl;for(int i=1;i<=2;i++){for(int j=1;j<=n;j++)cin>>M[j][i];}
}void initialize() //初始化函数
{for(int i=1;i<=n;i++)x[i]=i; //初始化当前作业调度的一种排列顺序bestf=10000; //此问题是得到最佳作业调度方案以便使其完成处理时间和达到最小,所以当前最优值bestf应该初始化赋值为较大的一个值
}
void outPut() //输出函数
{cout<<"这"<<n<<"个作业的最佳调度顺序为:"<<endl;for(int i=1;i<=n;i++)cout<<bestx[i]<<" ";cout<<endl;cout<<"该作业调度的完成时间和为:"<<endl;cout<<bestf<<endl;
}int main()
{inPut();initialize();Backtrack(1);outPut();return 0;
}
运行结果
批处理作业调度【回溯算法】相关推荐
- 批处理作业调度-回溯法
2019独角兽企业重金招聘Python工程师标准>>> 问题描述: 给定n个作业,集合J=(J1,J2,J3).每一个作业Ji都有两项任务分别在2台机器上完成.每个作业必须先有机器1 ...
- 算法设计与分析——回溯法——批处理作业调度
问题描述:给定n个作业的集合{J1,J2,-,Jn}.每个作业必须先由机器1处理,然后由机器2处理.作业Ji需要机器j的处理时间为tji.对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时 ...
- 算法设计与分析——第五章回溯法 批处理作业调度 + 最大团问题+图的m着色问题
文章目录 6.批处理作业调度(排列树) 7.最大团问题 8.图的m着色问题 6.批处理作业调度(排列树) 每一个作业Ji都有两项任务分别在2台机器上完成.每个作业必须先有机器1处理,然后再由机器2处理 ...
- 回溯法——批处理作业调度
问题描述 给定 n 个作业的集合 j = {j1, j2, ..., jn}.每一个作业 j[i] 都有两项任务分别在两台机器上完成.每一个作业必须先由机器1 处理,然后由机器2处理.作业 j ...
- 通用解题法——回溯算法(理解+练习)
积累算法经验,积累解题方法--回溯算法,你必须要掌握的解题方法! 什么是回溯算法呢? 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就&quo ...
- 用栈、回溯算法设计迷宫程序
目录 1.走迷宫与回溯算法 2.迷宫设计栈扮演的角色 3.Python实现走迷宫 栈的应用有许多,本篇博文着重将栈与回溯(Backtracking)算法结合,设计走迷宫程序.其实回溯算法也是人工智能的 ...
- 数字拆分问题算法回溯_回溯算法:求子集问题!
给「代码随想录」一个星标吧! ❝ 认识本质之后,这就是一道模板题 通知:我将公众号文章和学习相关的资料整理到了Github :https://github.com/youngyangyang04/le ...
- C语言回溯算法解决N皇后问题
回溯算法的模型是 x++, not satisfy ? x-- : continue. 代码中x作列号,y[x]保存第x列上皇后放置的位置. 1 #include<stdio.h> 2 # ...
- 从电影《蝴蝶效应》中学习回溯算法的核心思想
点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 关注我们丨文末赠书 深度优先搜索算法利用的是回溯算法思想.这个算法思 ...
- 回溯算法——算法总结(四)
回溯算法也叫试探法,它是一种系统地搜索问题的解的方法.回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试.用回溯算法解决这个问题的一般步骤为: 1.定义一个解空间.它包括问题 ...
最新文章
- javaweb学习总结二十五(response对象的用法一)
- POJ 1321 棋盘问题【DFS】
- 镜头视场角计算工具_什么是变焦镜头 变焦镜头介绍【详解】
- SAP Revenue Cloud业务综述
- 【iHMI43 4.3寸液晶模块】demo例程(版本1.02)发布
- 矩阵论:向量求导/微分和矩阵微分
- HashTable VS Dictionary
- 综述|重邮高新波等最新《少样本目标检测算法》
- 【Android 四大组件之Content Provider】一文吃透 BroadcastReceiver 广播接收器
- python基础语法看一篇就够了,全网最全python语法笔记汇总
- 2022-2027年(新版)中国产权交易行业前景动态与未来发展形势报告
- Java实现 LeetCode 686 重复叠加字符串匹配
- Python实现人脸识别,一行代码,多种功能,易上手又好操作
- java 下拉复选框_JAVA个人小程序GUI篇-收银(标签、按钮、复选框、下拉标、文本域、表格······)...
- html表单元素占位符是,HTML各种表单元素模板及写法
- MATLAB-一维插值运算
- Joan Baez - Jackaroe
- 巧用年线抓长线牛股的四种经典技巧
- 从客户端到后台,一文通吃
- PHP笔记-虚拟空间(虚拟主机)上部署Laravel5.7