独立任务最优调度问题(DP)

424 阅读1分钟

题目描述

22 台处理机 AABB 处理 nn 个作业。

设第 ii 个作业交给机器 AA 处理时需要时间 aia_i,若由机器 BB 来处理,则需要时间 bib_i。由于各作业的特点和机器的性能关系,很可能对于某些 ii,有 aibia_i\ge b_i,而对于某些 jj, jij≠i,有 ajbja_j\le b_j。既不能将一个作业分开由 22 台机器处理,也没有一台机器能同时处理2个作业。

题目分析

分析问题我们发现,每个任务只有两种选择,即由 AABB 处理,于是我们便可以想到暴力的解法,即依次对每个任务的两种选择进行枚举,记录 AABB 所用时间中较大值的最小值。时间复杂度为 O(2n)O(2^n)

接下来考虑动态规划进行优化。

三维动态规划

定义 a[i],b[i]a[i],b[i] 表示第 ii 项任务交给 AABB 机器完成所需要的时间,f[i][j][k]f[i][j][k] 表示是否可以使用 AA 机器时间 iiBB 机器时间 jj 的情况下完成前 kk 个任务。

首先定义 ABA,B 机器最大用时 mm,即 ABA,B 单独工作时间 mm 的情况下,均能够完成 kk 个任务。f[i][j][k]f[i][j][k]11 则表示可以完成,为 00 则表示无法完成。初始化 f[0m][0m][0]f[0~m][0~m][0]11,意为任意时间均可完成 00 项任务。

转移方程为 f[i][j][k]=f[ia[k]]f[i][jb[k]][k1]f[i][j][k] = f[i-a[k]] | f[i][j-b[k]][k-1],意为在完成前 k1k-1 项任务后,在当前时间限制下,机器A能否留出时间 a[k]a[k]BB 机器能否留出时间 b[k]b[k] 完成任务 kk

最终答案为完成 kk 项任务的 i,j{i,j} 对中较大值的最小值。

Accept 核心代码

for (int i = 0; i <= m; i ++)
    for (int j = 0; j <= m; j ++)
        f[i][j][0] = 1;
for (int k = 1; k <= n; k ++)
    for (int i = 0; i <= m; i ++)
        for (int j = 0; j <= m; j ++)
        {
            if (i >= a[k]) f[i][j][k] |= f[i - a[k]][j][k - 1];
            if (j >= b[k]) f[i][j][k] |= f[i][j - b[k]][k - 1];
        }
int res = 100;
for (int i = 0; i <= m; i ++)
    for (int j = 0; j <= m; j ++)
        if (f[i][j][n])
        {
            res = min(res, max(i, j));
            break;
        }
cout << res << "\n";