贪心-多机调度问题

多机调度问题分析

问题描述

在多机调度问题中,我们有 n 个独立的作业和 m 个相同的机器。每个作业 i 需要处理时间 ti。我们的目标是找到一个调度方案,使得所有作业尽可能快地完成。

贪心策略

  • 最长处理时间优先:优先分配处理时间最长的作业到最先可用的机器上。

情况分类

A: n < m

在这种情况下,每个作业可以独立地分配给一个机器,因为有足够的机器来处理所有作业。

B: n > m

当作业数超过机器数时,我们需要更智能的调度策略。以下是一个具体的例子:

示例

设有7个独立作业 {1, 2, 3, 4, 5, 6, 7} 由3台机器 {M1, M2, M3} 加工处理,各作业所需的处理时间分别为 {2, 14, 4, 16, 6, 5, 3}

贪心算法步骤

  1. 作业排序:首先,将作业按处理时间降序排序。

  2. 初始分配:将排序后的前 m 个作业分配给 m 台机器。

  3. 剩余作业分配:对于剩余的作业,将它们分配给当前完成时间最短的机器。

  4. 计算完成时间:最后,找出所有机器中完成时间最长的机器,该时间即为最短完成时间。

    在这里插入图片描述

贪心策略

采用贪心策略,优先处理花费时间长的任务。具体步骤如下:

  1. 作业排序:将作业按处理时间降序排序,确保最长的作业最先被考虑。
  2. 分配作业:将排序后的作业依次分配给最先空闲的机器。
  3. 计算完成时间:通过比较各台机器的占用时间,找出最大值,即为最短完成时间。

步骤

  1. 作业排序
    在这里插入图片描述

  2. 作业分配

    • 机器 M1 分配作业 4,时间为16
    • 机器 M2 分配作业 2,时间为14
    • 机器 M3 分配作业 5,时间为6
    • 在时间为6时,机器 M3 先结束,此时剩余任务里时间最长的是任务6,时间为5,选择任务6
    • 在时间为11时,机器 M3 先结束,此时剩余任务里时间最长的是任务3,时间为4,选择任务6
    • 在时间为14时,机器 M2 先结束,此时剩余任务里时间最长的是任务7,时间为3,选择任务7
    • 在时间为15时,机器 M3 先结束,此时剩余任务里时间最长的是任务1,时间为2,选择任务1
  3. 计算完成时间:比较各台机器的占用时间,找出最大值为17。
    在这里插入图片描述

代码:

#include<stdio.h> // 包含标准输入输出库,用于执行输入输出操作。

#define SIZE 100 // 定义一个宏SIZE,表示数组的最大大小。

// 函数声明,用于获取数组中的最小值。
int getmin(int a[], int n) {
    int min=0, i; // 初始化最小值索引为0,声明循环变量i。
    for(i = 0; i < n; i++) { // 遍历数组。
        if(a[i] < a[min]) // 如果当前元素小于已知最小值。
            min = i; // 更新最小值索引。
    }
    return min; // 返回最小值的索引。
}

// 函数声明,用于获取数组中的最大值。
int getmax(int a[], int n) {
    int max, i; // 声明最大值索引max,初始化为第一个元素的索引。
    a[max] = a[0]; // 将数组的第一个元素赋值给max。
    for(i = 0; i < n; i++) { // 遍历数组。
        if(a[i] > a[max]) // 如果当前元素大于已知最大值。
            max = i; // 更新最大值索引。
    }
    return max; // 返回最大值的索引。
}

int main() {
    int m, n, a[SIZE]; // 声明机器数m,作业数n,以及大小为SIZE的作业时间数组a。
    printf("请输入有几台机器:"); // 提示用户输入机器数。
    scanf("%d", &m); // 读取用户输入的机器数。
    printf("请输入有几个作业:"); // 提示用户输入作业数。
    scanf("%d", &n); // 读取用户输入的作业数。
    printf("请分别写出:"); // 提示用户输入每个作业的时间。
    for(int i = 0; i < n; i++) { // 循环读取每个作业的时间。
        scanf("%d", &a[i]); // 读取用户输入的作业时间。
    }
    
    // 冒泡排序,将作业时间从小到大排序。
    for(int i=0; i<n; i++) { 
        for(int j=i; j<n; j++) { // 内层循环进行相邻元素的比较。
            if(a[i] > a[j]) { // 如果前一个元素大于后一个元素。
                int tmp = a[j]; // 临时变量存储后一个元素的值。
                a[j] = a[i]; // 将前一个元素的值赋给后一个元素。
                a[i] = tmp; // 将临时变量的值赋给前一个元素。
            }
        }
    }
    
    // 将排序后的数组最大值(即最长作业时间)分配给m台机器。
    int w[SIZE]; // 声明一个数组w,用于存储每台机器的作业时间。
    for(int i=0; i<m; i++) {
        w[i] = a[n-i-1]; // 将排序后的数组的最后m个元素(最长的作业)分配给机器。
    }
    
    // 将剩余的作业时间分配给机器,使得完成时间最短。
    for(int j=n-m-1; j>=0; j--) {
        int t = getmin(w,m); // 找到当前机器中作业时间最短的机器。
        w[t] += a[j]; // 将当前作业时间加到该机器上。
    }
    
    // 计算并输出最短完成时间。
    int min = w[getmax(w,m)]; // 找到所有机器中作业时间最长的机器的时间。
    printf("最短时间为:%d", min); // 输出最短完成时间。
    return 0; // 程序结束。
}

运行截图:

在这里插入图片描述

  • 19
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值