首页 > 其他分享 >流水调度问题-动态规划-Johnson法则-两种方法

流水调度问题-动态规划-Johnson法则-两种方法

时间:2023-05-25 16:32:45浏览次数:38  
标签:bi 法则 Johnson int 作业 调度 value NumType


问题描述:

n个作业{0, 1, 2, …, n}在2台机器上M1 和M2 组成的流水线上完成加工。每个作业加工的顺序都是先在M1 上加工,后在M2 上加工。在两台机器上加工的时间分别为ai 和bi 。 确定这n个作业的加工顺序,使得从第一台作业开始加工,到最后一个作业完成加工所需要的时间最少。 

递归关系:

T(S, t) = min{ ai + T(S - {i}, bi) } 1  <= i <= n;

Johnson法则:

对于流水作业调度问题,必定存在一个最优调度π, 使得作业π(i)和π(i + 1)满足Johnson不等式 min{bπ(i), aπ(i + 1)} >= min{bπ(i + 1), aπ(i )}。

解题思路:

 方法1:

当min{ a1, a2,┅, an , b1, b2,┅, bn }=ak时,则对任何i≠k,都有min{bk, ai} ≥ min{bi,ak}成立,故此时应将作业k安排在最前面,作为最优调度的第一个执行的作业;
当min{ a1, a2,..., an , b1, b2, ..., bn }= bk时,则对任何i≠k,也都有min{bi,ak}≥min{bk,ai}成立,故此时应将作业k安排在最后面,作为最优调度的最后一个执行的作业。
n个作业中首先开工(或最后开工)的作业确定之后,对剩下的n-1个作业采用相同方法可再确定其中的一个作业,应作为n-1个作业中最先或最后执行的作业;反复使用这个方法直到最后只剩一个作业为止,最优调度就确定了 。
流程:
1. 将{a1,a2,…,an,b1,b2,…,bn}排成非递减序列;
2. 依次从序列中抽出最小元素m,如果m = aj且作业j还没有排入调度表,则把作业 j 安排在调度表可达的最左边一项空位上(设n个作业的调度表有n项,开始全部为空)。
3. 如果m = bj且作业j还没有排入调度表,则把作业j安排在调度表可达的最右边一项空位上。
4.如果作业j已排在调度表中,则取序列的下一个最小元素m,继续按上述方法调度,直到元素取完为止。
最后得到的调度表中的作业的顺序就是各作业的加工顺序。
例  设n = 4,
(a1,a2,a3,a4)=(3,4,8,10),
(b1,b2,b3,b4)=(6,2,9,15),
经排序后为
(b2,a1,a2,b1,a3,b3,a4,b4)=(2,3,4,6,8,9,10,15)。
设σ1,σ2,σ3,σ4是最优调度。

因为最小数是b2,故置σ4= 2。下一个次小的数是a1,置σ1= 1。接下去是a2,作业2已经被调度。再其次是b1作业1也已经被调度。下一个是a3,置σ2= 3,依次置σ3= 4。

代码:

/*

测试样例
输入:
4
3 6 4 2 8 9 10 10
输出
1 3 4 2

*/
#include <bits/stdc++.h>
using namespace std;
class NumType
{
public:
    int value;  //值
    int type;  //是a, 还是b
    int id;   //作业的id
public:
    NumType(){ }
    NumType(int v, int t, int i):value(v), type(t), id(i){ }
public:
    void SetValue(int v, int t, int i)
    {
        value = v, type = t, id = i;
    }
public:
    bool operator < (const NumType &a) const
    {
        return value < a.value;
    }
};
int n;
int p[1024]; //最优调度
int used[1024];  //作业i是否调度过
NumType N[1024];
void Input()
{
    int a, b;
    scanf("%d", &n);
    for(int i = 1, j = 0; i <= n; ++i)
    {
        scanf("%d %d", &a, &b);
        N[j++].SetValue(a, 0, i);
        N[j++].SetValue(b, 1, i);
    }
}
bool compare(const NumType &a, const NumType &b)
{
    return a < b;
}
void FlowShop()
{
    int endnum = n * 2;
    sort(N, N + 2 * n - 1);//sort(N, N + 2 * n - 1, compare);
    memset(used, 0, sizeof(used));
    memset(p, 0, sizeof(p));
    for(int i = 0, left = 1, right = n; i < endnum; ++i)
    {
        if(used[N[i].id] == 0)
        {
            if(N[i].type == 0)
            {
              p[left++] =  N[i].id;
              used[N[i].id] = 1;
            }
            else
            {
                p[right--] = N[i].id;
                used[N[i].id] = 1;
            }
        }
        else
            continue;
    }
}
void OutPut()
{
    for(int i = 1; i <= n; ++i)
    {
        cout << p[i] << " ";
    }
}
int main()
{
    Input();
    FlowShop();
    OutPut();

}

方法二:

流水作业调度问题的Johnson算法
(1)令N1 = { i | ai < bi}, N2 = { i | ai >= bi };
(2)将N1中作业依ai的非减序排序;将N2中作业依bi的非增序排序;

(3)N1中作业接N2中作业构成满足Johnson法则的最优调度。

流水调度问题-动态规划-Johnson法则-两种方法_#include

#include <bits/stdc++.h>
using namespace std;
class NumType
{
public:
    int value;
    int id;
public:
    NumType(){ }
    NumType(int v, int i):value(v), id(i){ }
public:
    void SetValue(int v, int i)
    {
        value = v, id = i;
    }
public:
//    bool operator < (const NumType &a) const
//    {
//        return value < a.value;
//    }
//    bool operator > (const NumType &a)const
//    {
//        return value > a.value;
//    }
};
int n, n_a, n_b;
int p[1024], a_v[1024], b_v[1024];
NumType A[1024]; // ai  < bi
NumType B[1024]; // ai >= bi
void Input()
{
    int a, b;
    n_a = n_b = 0;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d %d", &a, &b);
        a_v[i] = a, b_v[i] = b;
        if(a < b)
        {
            A[n_a++].SetValue(a, i);
        }
        else
            B[n_b++].SetValue(b, i);
    }
}
bool compare_a(const NumType &a, const NumType &b)
{
    return a.value < b.value;
}
void FlowShop()
{
    memset(p, 0, sizeof(p));
    sort(A, A + n_a, compare_a);
    sort(B, B + n_b, compare_a);
//    for(int i = 0; i < n_a; ++i)
//        cout << A[i].id << " ";
//        cout << endl;
//     for(int i = 0; i < n_b; ++i)
//        cout << B[i].id << " ";
//        cout << endl;
    for(int i = 0; i < n_a; ++i)
        p[i + 1] = A[i].id;
    for(int i = 0; i < n_b; ++i)
        p[n - i] = B[i].id;
}
void OutPut()
{
    int time_a = a_v[p[1]];
    int time_b = time_a + b_v[p[1]];
    for(int i = 2; i <= n; ++i)
    {
        time_a += a_v[p[i]];
        time_b = time_a < time_b ? time_b + b_v[p[i]] : time_a + b_v[p[i]];
    }
    cout << "加工总时间为 : " << time_b << endl;
    cout << "加工顺序为: " << endl;
    for(int i = 1; i <= n; ++i)
    {
        cout << p[i] << " ";
    }
}
int main()
{
    Input();
    FlowShop();
    OutPut();
}
方法二运行截图:

流水调度问题-动态规划-Johnson法则-两种方法_动态规划_02

标签:bi,法则,Johnson,int,作业,调度,value,NumType
From: https://blog.51cto.com/u_16129621/6349657

相关文章

  • Quartz.Net 调度器
    首先需要引入Quartz.Net的命名空间,例如: usingQuartz;usingQuartz.Impl;​然后创建一个调度器工厂(SchedulerFactory),并使用该工厂创建一个调度器(IScheduler)对象: ISchedulerFactoryschedulerFactory=newStdSchedulerFactory();ISchedulerscheduler=await......
  • Johnson 全源最短路
    全源最短路,换一种说法就是n个单源最短路,可以用n次Bellman-Ford或SPFA,非负边权还可以用Dijkstra,可是有负边权用前两个算法还是慢,如果我们能把负边权映射成非负边权的话,一切就都好办了这里我们引入一个虚拟结点,它和所有点的初始距离都是0,然后,我们求出来这个结点和其他店的最短路h,然......
  • go语言调度gmp原理(5)
    go语言调度gmp原理(5)线程管理go语言的运行时会通过调度器改变线程的所有权,它也提供了runtime.lockOSthread和runtime.UnlockOSthread,让我们能绑定goroutine和线程完成一些比较特殊的操作。goroutine应该在调用操作系统服务或者依赖线程状态的非go语言库时调用runtime.lockOSTh......
  • LInux调度器
    本文结构前面4节先展开讲讲linux内核2.6.24版本的调度器实现,其中包括CFS调度器。然后对linux历史上出现过的O(1)和O(n)调度器做一个比较,看看它们的优缺点。优先级和调度策略linux中进程优先级在用户试图和内核视图两个方面有着不同表达。在用户层面,对普通进程优先级的描述通......
  • pod调度:节点选择与亲和
    0、简介k8s对于pod的调度有如下几种:按node名称、按标签、节点亲和、pod亲和1、使用nodeName指定节点场景:pod需要部署到指定节点。方案:[root@vmrootschedule-yamls]#catschedule-deloyment.yamlapiVersion:apps/v1kind:Deploymentmetadata:name:scdl-dspec:selector:......
  • 火山引擎DataLeap数据调度实例的 DAG 优化方案(三):技术实现
    在原始数据中,是以一个数组的形式返回节点信息及依赖关系。所以,需要对数据进行处理形成图所需要的数据,同时,利用多个map对数据进行存储,方便后续对数据进行检索,减少时间复杂度。实例节点的样式需要通过基础图形Text(文本)、Rect(矩形)、Icon(图标)进行组合,以达到我们的设计要求。......
  • Kubernetes 初始化容器及静态Pod和Pod调度策略
    初始化容器kubernetes1.3版本引入了initcontainer初始化容器特性。主要用于在启动应用容器(appcontainer)前来启动一个或多个初始化容器,作为应用容器的一个基础。#查看要修改的内核参数[root@kmaster~]#sysctl-a|grepvm.overcommit_ratiovm.overcommit_ratio=50#输......
  • DolohinScheduler 分布式任务调度框架 代码流程分解
    一、DS-API模块-执行工作流 -定时任务执行 更新schedule参数 -/schedule新增schedule参数做了什么事? 将schedule参数用ScheduleParam类进行解析 有效性校验,而后解析保存到t_ds_schedules表内,更新t_ds_process_definition表 -/onlin......
  • Linux进程调度-组调度及带宽控制
    1.概述组调度(task_group)是使用Linuxcgroup(controlgroup)的cpu子系统来实现的,可以将进程进行分组,按组来分配CPU资源等。比如,看一个实际的例子:A和B两个用户使用同一台机器,A用户16个进程,B用户2个进程,如果按照进程的个数来分配CPU资源,显然A用户会占据大量的CPU时间,这对于B用户......
  • 分布式系统关键技术:流量与数据调度
    1、流量调度与服务治理的关系服务治理时内部系统的事,流量调度可以是内部的,更是外部接入层的事。服务治理时数据中心的事,而流量调度要做的好,应该是数据中心之外的事,也就是我们常说的边缘计算或者CDN。 2、流量调度的主要功能和关键技术流量调度系统应该主要具备的功能:依据系......