1723. 完成所有工作的最短时间
以人数为阶段进行考虑,考虑再多一个人的情况下,根据任务的分配状况 s, 如何进行转移。
如果以任务的分配为阶段进行考虑,最好也就是 O ( n ! ) O(n!) O(n!)的复杂度了。
DP公式:
f
[
i
]
[
s
]
=
m
i
n
(
f
[
i
]
[
s
]
,
m
a
x
(
f
[
i
−
1
]
[
j
]
,
s
u
m
[
s
−
j
]
)
)
;
f[i][s] = min(f[i][s],max(f[i-1][j],sum[s - j]));
f[i][s]=min(f[i][s],max(f[i−1][j],sum[s−j]));
时间复杂度: O ( k ∗ 3 n ) O(k*3^n) O(k∗3n)
class Solution {
int low_idx(int x) {
int idx = 0;
while((x&1) == 0) {
idx++;
x >>= 1;
}
return idx;
}
public:
int minimumTimeRequired(vector<int>& jobs, int k) {
int n = jobs.size();
int limit = 1<<n;
vector<vector<int>> f(k+1,vector<int>(limit,(int)1e9));
// 预处理
vector<int> sum(limit);
for(int s = 1; s < limit; s++) {
int idx = low_idx(s);
sum[s] = sum[s - (1<<idx)] + jobs[idx];
}
// 初始化
f[1] = sum;
for(int i = 2; i <= k; i++) {
for(int s = 1; s < limit; s++) {
// f[i][s] = min(max(f[i-1][c],c'));
// 快速枚举子集
for(int j = s; j > 0; j = (j-1)&s) {
f[i][s] = min(f[i][s],max(f[i-1][j],sum[s - j]));
}
}
}
return f[k][limit-1];
}
};