问题描述
小R在教室里有N名学生和M名教职员工。每个教职员工的评估速度不同,评估每个学生所需的时间不同。你得到一个数组A,其中A[i]表示第i名教职员工对一名学生进行评估所需的时间(以分钟为单位)。
教职员工需要对所有学生进行评估,每名教职员工在任意时刻只能评估一名学生。评估完成后,教职员工可以立即开始评估下一名学生。你的任务是找到在这些条件下评估所有学生所需的最短总时间。
测试样例
样例1:
输入:
N = 2, M = 2, A = [3, 4]
输出:4
解释:两名教职员工可以同时工作。教职员工1(需要3分钟)评估一名学生,教职员工2(需要4分钟)评估一名学生。因此,总用时为 max(3, 4) = 4。
样例2:
输入:
N = 3, M = 2, A = [5, 7]
输出:10
解释:教职员工1(5分钟)评估两名学生,教职员工2(7分钟)评估1名学生。总用时为 max(5+5, 7) = 10。
样例3:
输入:
N = 5, M = 3, A = [2, 3, 5]
输出:6
解释:将学生分配为教职员工1(2分钟)评估3名,教职员工2(3分钟)评估1名,教职员工3(5分钟)评估1名。总用时为 max(2*3, 3, 5) = 6。
解题思路
本问题可以使用 动态规划 来解决,目的是最小化最大工作时间。动态规划的核心在于递归地分配学生,并记录最优分配结果。
状态定义
- dp[i][j] 表示用前 i名教职员工评估完成 j名学生的最短时间。
转移方程
-
边界条件:
- 当只有 1 名教职员工时,
dp[1][j] = A[0] * j,即单人评估完成所有学生的时间。 - 当只有 1 名学生时,
dp[i][1] = min(A[:i]),即找到评估一名学生所需时间最短的教职员工。
- 当只有 1 名教职员工时,
-
递推公式: 对于第 i 名教职员工评估 k 名学生:
- 剩余的
j-k名学生由前i-1名教职员工评估完成。 - 当前的最大评估时间为
max(dp[i-1][j-k], k * A[i-1])。
因此,递推公式为:
dp[i][j] = min(max(dp[i-1][j-k], k * A[i-1]) for k in range(j+1)) - 剩余的
代码展示
def solution(N: int, M: int, A: list) -> int:
dp = [ [0 for i in range(N+1)] for j in range(M+1)]
for i in range(1,M+1):
dp[i][1]=min(A[:i])
for j in range(1,N+1):
dp[1][j]=A[0]*j
for i in range(2,M+1):
for j in range(2,N+1):
dp[i][j]=min([max(dp[i-1][j-k],k*A[i-1]) for k in range(j+1)])
return dp[M][N]
复杂度分析
- 时间复杂度:填充动态规划表需要遍历所有教职员工和学生,且对于每个状态需要遍历分配可能性
O(j),因此时间复杂度为O(M * N^2)。 - 空间复杂度:动态规划表占用空间
O(M * N)。
总结
本文通过动态规划实现了对教职员工和学生任务的最优分配,解决了评估所需最短时间问题。