题目描述
给你一个整数数组 jobs ,其中 jobs[i] 是完成第 i 项工作要花费的时间。
请你将这些工作分配给 k 位工人。所有工作都应该分配给工人,且每项工作只能分配给一位工人。工人的 工作时间 是完成分配给他们的所有工作花费时间的总和。请你设计一套最佳的工作分配方案,使工人的 最大工作时间 得以 最小化 。
返回分配方案中尽可能 最小 的 最大工作时间 。
示例1
输入:jobs = [3,2,3], k = 3
输出:3
解释:给每位工人分配一项工作,最大工作时间是 3
示例2
输入:jobs = [1,2,4,7,8], k = 2
输出:11
解释:按下述方式分配工作:
1 号工人:1、2、8(工作时间 = 1 + 2 + 8 = 11)
2 号工人:4、7(工作时间 = 4 + 7 = 11)
最大工作时间是 11 。
解题思路
记录自题解
可以选择枚举工人,给每个工人分配工作,搜素的时候同时维护最大的工作时间,记录答案时维护最大工作时间的最小化。
剪枝:如果当前搜素分支的最大工作时间已经大于答案,那么就可以提前return
。
code(TLE)
class Solution {
public:
int n, k, ans = INT_MAX;
vector<int> jobs;
vector<int> sum;
int minimumTimeRequired(vector<int>& _jobs, int _k) {
jobs = _jobs;
k = _k;
n = jobs.size();
sum = vector<int>(n, 0);
dfs(0, 0);
return ans;
}
void dfs(int u, int maxt) {
if (maxt >= ans) return;
if (u == n) {
ans = maxt;
return;
}
for (int i = 0; i < k; i ++ ) {
sum[i] += jobs[u];
dfs(u + 1, max(maxt, sum[i]));
sum[i] -= jobs[u];
}
}
};
剪枝优化
然而上面的剪枝还不够彻底。**题目其实是让我们将n个数分为k份,并且尽可能让k分平均,这样[最大工作时间]才是最小的。**而我们上述的dfs
时将每个任务依次分给每个工人,相当于二叉树的一棵高度为n
的k
阶树。所以其实我们第一次更新的ans其实是最差的答案
朴素版的dfs是弱化了剪枝效果
想要最大化剪枝效果,并且让k
份平均的话,我们应当调整我们对于[递归树]的搜索方向:将任务优先分配给[空闲工人]
class Solution {
public:
int n, k, ans = INT_MAX;
vector<int> jobs;
vector<int> sum;
int minimumTimeRequired(vector<int>& _jobs, int _k) {
jobs = _jobs;
k = _k;
n = jobs.size();
sum = vector<int>(n, 0);
dfs(0, 0, 0);
return ans;
}
void dfs(int u, int used, int maxt) {
if (maxt >= ans) return;
if (u == n) {
ans = maxt;
return;
}
if (used < k) {
sum[used] = jobs[u];
dfs(u + 1, used + 1, max(maxt, sum[used]));
sum[used] = 0;
}
for (int i = 0; i < used; i ++ ) {
sum[i] += jobs[u];
dfs(u + 1, used, max(maxt, sum[i]));
sum[i] -= jobs[u];
}
}
};