【算法设计与分析】C++独立任务最优调度问题

一、问题描述:

  用2台处理机A和B处理n个作业。设第i个作业交给机器A处理时需要时间ai,若由机器B来处理,则需要时间bi。由于各作业的特点和机器的性能关系,很可能对于某些i,有ai>bi,而对于某些j,j≠i,有aj>bj。既不能将一个作业分开由2台机器处理,也没有一台机器能同时处理2个作业。设计一个动态规划算法,使得这2台机器处理完这n个作业的时间最短(从任何一台机器开工到最后一台机器停工的总时间)。

实例:

(a1,a2,a3,a4,a5,a6)=(2,5,7,10,5,2);

(b1,b2,b3,b4,b5,b6)=(3,8,4,11,3,4)。

对于给定的2台处理机A和B处理n个作业,找出一个最优调度方案,使2台机器处理完这n个作业的时间最短。

输入:

6
2 5 7 10 5 2
3 8 4 11 3 4

 输出:

15

二、思路分析

题目要求使用动态规划的算法,先给出状态转移方程:

F[i][j] = min(F[i-1][j-a[i]] , F[i-1][j]+b[i])

其中F[i][j]表示到第i个作业,A机器花费时间为j的情况下,B机器处理的最短时间

我们分为两种情况:

1、A处理机完成了第i个任务,那么B处理机完成k个任务的最短时间就与B处理机完成i-1个任务所需的最短时间是相同的,即F[i-1][j-a[i]]

2、B处理机完成了第i个任务,那么B处理机完成i个任务的最短时间就等于B处理机完成i-1个任务的最短时间加上B处理机完成第i个任务所需要的时间,即F[i-1][j]+b[i]

我们完成作业的最短时间是由A机器完成时间和B机器完成时间中较大的那一者来决定,因为一项作业的真正完工需要两个都完成才算完成。 所以在最终计算完成时间时,我们要取A、B完成时间的最大值,再根据每个不同j的取值(即分配给A机器花费时间j的不同情况下)循环遍历查找最小的那个,代码中为x代替j。

三、代码

#include <bits/stdc++.h>
#define MAXN 1005
using namespace std;
int a[MAXN];//机器A处理各作业的时间
int b[MAXN];//机器B处理各作业的时间
int F[MAXN][MAXN];
int time_[MAXN];//处理作业k所需要的最短时间
int n;

int dp() {
    int sumA = a[1];
    //k = 1的情况
    for(int x = 0; x < a[1]; x++) { //分配给A的时间小于A处理第一个作业所需时间,给B
        F[1][x] = b[1];
    }
    F[1][a[1]] = min(b[1],a[1]);//正好够A就看谁小
    //初始化
    for(int i = 2; i <= n; i++) {
        for(int j = 0; j <= n; j++) {
            F[i][j] = INT_MAX;
        }
    }
	//k >= 2的情况
    for(int k = 2; k <= n; k++) {
        sumA += a[k];
        time_[k] = INT_MAX;
        for(int x = 0; x <= sumA; x++) {
            if(x < a[k]) {
                F[k][x] = F[k-1][x] + b[k];
            } else {
                F[k][x] = min(F[k-1][x] + b[k], F[k-1][x-a[k]]);
            }
            time_[k] = min(time_[k],max(x,F[k][x]));
            //max(x,F[k][x])表示前k个作业机器A花费x分钟,B机器花费F[k][x]分钟情况下,最迟完工时间
        }
    }
    return time_[n];
}

int main() {
    printf("请输入作业数量:");
    scanf("%d",&n);
    printf("请输入机器A处理每个作业的时间:");
    for(int i = 1; i <= n; i++) {
        scanf("%d",&a[i]);
    }
    printf("请输入机器B处理每个作业的时间:");
    for(int i = 1; i <= n; i++) {
        scanf("%d",&b[i]);
    }
    printf("总的最少处理时间为:%d\n",dp());
    return 0;
}

### 回答1: 这是一道经典的任务调度问题,可以使用动态规划算法来解决。 首先,定义一个二维数组dp[i][j]表示前i个作业分配给a和b两台机器处理,其中a已经处理了j个作业的最短时间。则状态转移方程为: dp[i][j] = min(dp[i-1][j-1]+ai, dp[i-1][j]+bi) 其中,第i个作业可以分配给a或b两台机器处理,如果分配给a,则a已经处理了j-1个作业,需要加上ai的时间;如果分配给b,则a已经处理了j个作业,需要加上bi的时间。取两者中的最小值即可。 最终的答案为dp[n][n/2],即前n个作业分配给a和b两台机器处理,a已经处理了n/2个作业的最短时间。 对于给定的实例,可以得到以下的状态转移表: j 0 1 2 3 4 5 i 0 0 2 7 14 19 24 1 3 5 10 17 22 27 2 7 8 12 19 24 29 3 11 13 14 21 26 31 4 14 16 18 21 26 31 5 16 18 20 23 26 31 最终的答案为31,即两台机器处理完这6个作业的最短时间为31。 ### 回答2: 这道题可以采用动态规划的思想,用一个二维数组dp[i][j]表示a机器处理前i个作业,b机器处理前j个作业所需的最短时间,i和j都从0开始。 对于dp[i][j]的状态转移,分为以下两种情况: 1. 第i个作业交给a机器处理,第j个作业交给b机器处理。则dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + bi。 2. 第i个作业交给b机器处理,第j个作业交给a机器处理。则dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + ai。 最终的答案即为dp[n][n]。根据题目要求,不能将一个作业分开由两台机器处理,因此任意时刻a机器和b机器只能处理一个作业。 用给定的实例来说明: a = [2, 5, 7, 10, 5, 2], b = [3, 8, 4, 11, 3, 4] 设dp数组为6 x 6 的矩阵,初始值为0。 | | 0 | 1 | 2 | 3 | 4 | 5 | | --- |---|---|---|---|---|---| | 0 | 0 | 0 | 0 | 0 | 0 | 0 | | 1 | 3 | 0 | 0 | 0 | 0 | 0 | | 2 | 8 | 13 | 20 | 23 | 23 | 23 | | 3 | 12 | 23 | 33 | 46 | 49 | 53 | | 4 | 23 | 38 | 49 | 70 | 75 | 78 | | 5 | 28 | 46 | 63 | 78 | 83 | 88 | 在dp表格中,第i行第j列表示a机器处理前i个作业,b机器处理前j个作业所需的最短时间。根据状态转移方程,可以推导出每个元素的值。 例如dp[3][4],表示a机器处理前3个作业,b机器处理前4个作业所需的最短时间。这个值可以由上一个状态dp[2][4]和dp[3][3]转移而来,使用状态转移方程即可计算得到。 最终答案为dp[5][5] = 88,表示两台机器处理完这六个作业的时间最短为88。 ### 回答3: 这道题目可以使用动态规划算法来解决。我们设f[i][j]为前i个作业中,由机器A处理j个作业的最短时间。那么由机器B处理的作业个数为i-j个。 因此,状态转移方程为: f[i][j] = min(f[i-1][j]+a[i], f[i-1][j-1]+b[i]) (j≥1) f[i][0] = f[i-1][0]+a[i] 其中,第一条状态转移方程表示第i个作业由机器A处理,则前i-1个作业由机器A处理的数量是j,由机器B处理的数量是i-j,此时第i个作业由机器A处理,所需时间为a[i];第二条状态转移方程表示第i个作业由机器B处理,则前i-1个作业由机器A处理的数量是j-1,由机器B处理的数量是i-j-1,此时第i个作业由机器B处理,所需时间为b[i]。 为了求出最短时间,我们需要枚举所有的j,然后取其中的最小值,即: ans = min(f[n][j]+max(sum(a)-sum(b[j]), sum(b)-sum(a[j]))) 其中,sum(a)和sum(b)分别表示所有作业在机器A和机器B上处理所需的总时间,sum(a[j])和sum(b[j])分别表示前j个作业在机器A和机器B上处理所需的总时间。 最终的答案即为ans。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

7_lining

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值