题目描述
Bob 被困在了一个地窖里,他需要破解 n
个锁才能逃出地窖,每一个锁都需要一定的 能量 才能打开。每一个锁需要的能量存放在一个数组 strength
里,其中 strength[i]
表示打开第 i
个锁需要的能量。
Bob 有一把剑,它具备以下的特征:
- 一开始剑的能量为 0 。
- 剑的能量增加因子
X
一开始的值为 1 。
- 每分钟,剑的能量都会增加当前的
X
值。
- 打开第
i
把锁,剑的能量需要到达 至少 strength[i]
。
- 打开一把锁以后,剑的能量会变回 0 ,
X
的值会增加一个给定的值 K
。
你的任务是打开所有 n
把锁并逃出地窖,请你求出需要的 最少 分钟数。
请你返回 Bob 打开所有 n
把锁需要的 最少 时间。
示例 1:
输入:strength = [3,4,1], K = 1
输出:4
解释:
时间 |
能量 |
X |
操作 |
更新后的 X |
0 |
0 |
1 |
什么也不做 |
1 |
1 |
1 |
1 |
打开第 3 把锁 |
2 |
2 |
2 |
2 |
什么也不做 |
2 |
3 |
4 |
2 |
打开第 2 把锁 |
3 |
4 |
3 |
3 |
打开第 1 把锁 |
3 |
无法用少于 4 分钟打开所有的锁,所以答案为 4 。
示例 2:
输入:strength = [2,5,4], K = 2
输出:5
解释:
时间 |
能量 |
X |
操作 |
更新后的 X |
0 |
0 |
1 |
什么也不做 |
1 |
1 |
1 |
1 |
什么也不做 |
1 |
2 |
2 |
1 |
打开第 1 把锁 |
3 |
3 |
3 |
3 |
什么也不做 |
3 |
4 |
6 |
3 |
打开第 2 把锁 |
5 |
5 |
5 |
5 |
打开第 3 把锁 |
7 |
无法用少于 5 分钟打开所有的锁,所以答案为 5 。
提示:
n == strength.length
1 <= n <= 8
1 <= K <= 10
1 <= strength[i] <= 106
解法
方法一
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def findMinimumTime(self, strength: List[int], K: int) -> int:
@cache
def dfs(i: int) -> int:
if i == (1 << len(strength)) - 1:
return 0
cnt = i.bit_count()
x = 1 + cnt * K
ans = inf
for j, s in enumerate(strength):
if i >> j & 1 ^ 1:
ans = min(ans, dfs(i | 1 << j) + (s + x - 1) // x)
return ans
return dfs(0)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32 | class Solution {
private List<Integer> strength;
private Integer[] f;
private int k;
private int n;
public int findMinimumTime(List<Integer> strength, int K) {
n = strength.size();
f = new Integer[1 << n];
k = K;
this.strength = strength;
return dfs(0);
}
private int dfs(int i) {
if (i == (1 << n) - 1) {
return 0;
}
if (f[i] != null) {
return f[i];
}
int cnt = Integer.bitCount(i);
int x = 1 + cnt * k;
f[i] = 1 << 30;
for (int j = 0; j < n; ++j) {
if ((i >> j & 1) == 0) {
f[i] = Math.min(f[i], dfs(i | 1 << j) + (strength.get(j) + x - 1) / x);
}
}
return f[i];
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | class Solution {
public:
int findMinimumTime(vector<int>& strength, int K) {
int n = strength.size();
int f[1 << n];
memset(f, -1, sizeof(f));
int k = K;
auto dfs = [&](this auto&& dfs, int i) -> int {
if (i == (1 << n) - 1) {
return 0;
}
if (f[i] != -1) {
return f[i];
}
int cnt = __builtin_popcount(i);
int x = 1 + k * cnt;
f[i] = INT_MAX;
for (int j = 0; j < n; ++j) {
if (i >> j & 1 ^ 1) {
f[i] = min(f[i], dfs(i | 1 << j) + (strength[j] + x - 1) / x);
}
}
return f[i];
};
return dfs(0);
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | func findMinimumTime(strength []int, K int) int {
n := len(strength)
f := make([]int, 1<<n)
for i := range f {
f[i] = -1
}
var dfs func(int) int
dfs = func(i int) int {
if i == 1<<n-1 {
return 0
}
if f[i] != -1 {
return f[i]
}
x := 1 + K*bits.OnesCount(uint(i))
f[i] = 1 << 30
for j, s := range strength {
if i>>j&1 == 0 {
f[i] = min(f[i], dfs(i|1<<j)+(s+x-1)/x)
}
}
return f[i]
}
return dfs(0)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | function findMinimumTime(strength: number[], K: number): number {
const n = strength.length;
const f: number[] = Array(1 << n).fill(-1);
const dfs = (i: number): number => {
if (i === (1 << n) - 1) {
return 0;
}
if (f[i] !== -1) {
return f[i];
}
f[i] = Infinity;
const x = 1 + K * bitCount(i);
for (let j = 0; j < n; ++j) {
if (((i >> j) & 1) == 0) {
f[i] = Math.min(f[i], dfs(i | (1 << j)) + Math.ceil(strength[j] / x));
}
}
return f[i];
};
return dfs(0);
}
function bitCount(i: number): number {
i = i - ((i >>> 1) & 0x55555555);
i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);
i = (i + (i >>> 4)) & 0x0f0f0f0f;
i = i + (i >>> 8);
i = i + (i >>> 16);
return i & 0x3f;
}
|