• 问题描述

给定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=1n​F2i​称为该作业调度的完成时间和。可以证明,当作业以相同次序在机器1和机器2上完成处理时,可以得到一种最佳调度,即使该作业调度的完成时间和最小。(证明略)

  • 问题解读

  1. 对于给定的n个作业,指定最佳作业调度方案,使其完成时间和最小,因此是求一个最优值
  2. 调度必须遵循:
    ① 一个作业必须先由机器1处理,再由机器2处理,顺序不可颠倒;
    ② 机器1处理n个作业的顺序必须和机器2处理n个作业的顺序相同(因为只有这样才能使作业调度的完成时间和最小)。
  3. 由于是一种作业调度顺序的方案,因此该问题的解空间树是排列树
  • 实例分析

如下图,给出了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先在机器1上处理,处理完后紧接着在机器2上处理。对应红线部分,这时作业1在机器2上完成处理的时间为2,F21F{21}F21=3;
  2. 作业2 需要在机器1上完成的任务可以紧接着作业1在机器1上处理,但需要在机器2上完成的任务就要看作业2在机器1上完成处理的时间晚,还是作业1在机器2上完成处理的时间晚。如图,显然作业2 需要在机器1上完成的任务完成的时间较晚,因此作业2需要在机器1上完成后才能在机器2上继续完成。作业2的处理对应蓝线部分,这时作业2在机器2上完成处理的时间为2,F22F{22}F22=7;
  3. 同作业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=13​F2i​ = 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;
}
  • 运行结果

批处理作业调度【回溯算法】相关推荐

  1. 批处理作业调度-回溯法

    2019独角兽企业重金招聘Python工程师标准>>> 问题描述: 给定n个作业,集合J=(J1,J2,J3).每一个作业Ji都有两项任务分别在2台机器上完成.每个作业必须先有机器1 ...

  2. 算法设计与分析——回溯法——批处理作业调度

    问题描述:给定n个作业的集合{J1,J2,-,Jn}.每个作业必须先由机器1处理,然后由机器2处理.作业Ji需要机器j的处理时间为tji.对于一个确定的作业调度,设Fji是作业i在机器j上完成处理的时 ...

  3. 算法设计与分析——第五章回溯法 批处理作业调度 + 最大团问题+图的m着色问题

    文章目录 6.批处理作业调度(排列树) 7.最大团问题 8.图的m着色问题 6.批处理作业调度(排列树) 每一个作业Ji都有两项任务分别在2台机器上完成.每个作业必须先有机器1处理,然后再由机器2处理 ...

  4. 回溯法——批处理作业调度

    问题描述     给定 n 个作业的集合 j = {j1, j2, ..., jn}.每一个作业 j[i] 都有两项任务分别在两台机器上完成.每一个作业必须先由机器1 处理,然后由机器2处理.作业 j ...

  5. 通用解题法——回溯算法(理解+练习)

    积累算法经验,积累解题方法--回溯算法,你必须要掌握的解题方法! 什么是回溯算法呢? 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就&quo ...

  6. 用栈、回溯算法设计迷宫程序

    目录 1.走迷宫与回溯算法 2.迷宫设计栈扮演的角色 3.Python实现走迷宫 栈的应用有许多,本篇博文着重将栈与回溯(Backtracking)算法结合,设计走迷宫程序.其实回溯算法也是人工智能的 ...

  7. 数字拆分问题算法回溯_回溯算法:求子集问题!

    给「代码随想录」一个星标吧! ❝ 认识本质之后,这就是一道模板题 通知:我将公众号文章和学习相关的资料整理到了Github :https://github.com/youngyangyang04/le ...

  8. C语言回溯算法解决N皇后问题

    回溯算法的模型是 x++, not satisfy ? x-- : continue. 代码中x作列号,y[x]保存第x列上皇后放置的位置. 1 #include<stdio.h> 2 # ...

  9. 从电影《蝴蝶效应》中学习回溯算法的核心思想

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 关注我们丨文末赠书 深度优先搜索算法利用的是回溯算法思想.这个算法思 ...

  10. 回溯算法——算法总结(四)

    回溯算法也叫试探法,它是一种系统地搜索问题的解的方法.回溯算法的基本思想是:从一条路往前走,能进则进,不能进则退回来,换一条路再试.用回溯算法解决这个问题的一般步骤为: 1.定义一个解空间.它包括问题 ...

最新文章

  1. javaweb学习总结二十五(response对象的用法一)
  2. POJ 1321 棋盘问题【DFS】
  3. 镜头视场角计算工具_什么是变焦镜头 变焦镜头介绍【详解】
  4. SAP Revenue Cloud业务综述
  5. 【iHMI43 4.3寸液晶模块】demo例程(版本1.02)发布
  6. 矩阵论:向量求导/微分和矩阵微分
  7. HashTable VS Dictionary
  8. 综述|重邮高新波等最新《少样本目标检测算法》
  9. 【Android 四大组件之Content Provider】一文吃透 BroadcastReceiver 广播接收器
  10. python基础语法看一篇就够了,全网最全python语法笔记汇总
  11. 2022-2027年(新版)中国产权交易行业前景动态与未来发展形势报告
  12. Java实现 LeetCode 686 重复叠加字符串匹配
  13. Python实现人脸识别,一行代码,多种功能,易上手又好操作
  14. java 下拉复选框_JAVA个人小程序GUI篇-收银(标签、按钮、复选框、下拉标、文本域、表格······)...
  15. html表单元素占位符是,HTML各种表单元素模板及写法
  16. MATLAB-一维插值运算
  17. Joan Baez - Jackaroe
  18. 巧用年线抓长线牛股的四种经典技巧
  19. 从客户端到后台,一文通吃
  20. PHP笔记-虚拟空间(虚拟主机)上部署Laravel5.7

热门文章

  1. 攻防世界逆向初级训练
  2. 【算法训练营】 - 顺丰科技智慧物流校园技术挑战赛
  3. 江苏大学计算机学院段学庆,李致远-江苏大学计算机科学与通信工程学院
  4. 获取某年某月的最后一天
  5. 开题报告:基于java在线外卖点餐送餐系统 毕业设计论文开题报告模板
  6. 激光三角测量法在工业视觉检测上的应用
  7. android app闪退原因总结分析
  8. 调用第三方接口大致流程
  9. 【Handler】IdleHandler
  10. 基于JSP+SSM的网上商城购物网站设计