You are given an integer array power where power[i] is the power of the
ith monster.
You start with 0 mana points, and each day you increase your mana points by
gain where gain initially is equal to 1.
Each day, after gaining gain mana, you can defeat a monster if your mana points are greater than or equal to the power of that monster. When you defeat a monster:
your mana points will be reset to 0, and
the value of gain increases by 1.
Return theminimum number of days needed to defeat all the monsters.
Input: power =[3,1,4]Output: 4Explanation: The optimal way to beat all the monsters is to:- Day 1: Gain 1 mana point to get a total of 1 mana point. Spend all mana points to kill the 2nd monster.- Day 2: Gain 2 mana points to get a total of 2 mana points.- Day 3: Gain 2 mana points to get a total of 4 mana points. Spend all mana points to kill the 3rd monster.- Day 4: Gain 3 mana points to get a total of 3 mana points. Spend all mana points to kill the 1st monster.It can be proven that 4is the minimum number of days needed.
Example 2:
1
2
3
4
5
6
7
8
Input: power =[1,1,4]Output: 4Explanation: The optimal way to beat all the monsters is to:- Day 1: Gain 1 mana point to get a total of 1 mana point. Spend all mana points to kill the 1st monster.- Day 2: Gain 2 mana points to get a total of 2 mana points. Spend all mana points to kill the 2nd monster.- Day 3: Gain 3 mana points to get a total of 3 mana points.- Day 4: Gain 3 mana points to get a total of 6 mana points. Spend all mana points to kill the 3rd monster.It can be proven that 4is the minimum number of days needed.
Example 3:
1
2
3
4
5
6
7
8
9
10
Input: power =[1,2,4,9]Output: 6Explanation: The optimal way to beat all the monsters is to:- Day 1: Gain 1 mana point to get a total of 1 mana point. Spend all mana points to kill the 1st monster.- Day 2: Gain 2 mana points to get a total of 2 mana points. Spend all mana points to kill the 2nd monster.- Day 3: Gain 3 mana points to get a total of 3 mana points.- Day 4: Gain 3 mana points to get a total of 6 mana points.- Day 5: Gain 3 mana points to get a total of 9 mana points. Spend all mana points to kill the 4th monster.- Day 6: Gain 4 mana points to get a total of 4 mana points. Spend all mana points to kill the 3rd monster.It can be proven that 6is the minimum number of days needed.
Since the number of monsters is small (<= 17), we can use bitmask DP to try all possible orders of killing monsters. For each state, we track the minimum days needed and the current gain value. The key is to choose the next monster to kill such that the required mana can be accumulated in the fewest days.
classSolution {
public:int minimumTime(vector<int>& power) {
int n = power.size();
vector<vector<int>> dp(1<<n, vector<int>(n+1, INT_MAX));
dp[0][1] =0;
for (int mask =0; mask < (1<<n); ++mask) {
for (int gain =1; gain <= n; ++gain) {
if (dp[mask][gain] == INT_MAX) continue;
for (int i =0; i < n; ++i) {
if (!(mask & (1<<i))) {
int mana =0, days =0;
while (mana < power[i]) {
mana += gain;
days++;
}
int nmask = mask | (1<<i);
if (dp[nmask][gain+1] > dp[mask][gain] + days)
dp[nmask][gain+1] = dp[mask][gain] + days;
}
}
}
}
int ans = INT_MAX;
for (int gain =1; gain <= n; ++gain)
ans = min(ans, dp[(1<<n)-1][gain]);
return ans;
}
};
classSolution {
publicintminimumTime(int[] power) {
int n = power.length;
int[][] dp =newint[1<<n][n+2];
for (int[] row : dp) Arrays.fill(row, Integer.MAX_VALUE);
dp[0][1]= 0;
for (int mask = 0; mask < (1<<n); mask++) {
for (int gain = 1; gain <= n; gain++) {
if (dp[mask][gain]== Integer.MAX_VALUE) continue;
for (int i = 0; i < n; i++) {
if ((mask & (1<<i)) == 0) {
int mana = 0, days = 0;
while (mana < power[i]) {
mana += gain;
days++;
}
int nmask = mask | (1<<i);
if (dp[nmask][gain+1]> dp[mask][gain]+ days)
dp[nmask][gain+1]= dp[mask][gain]+ days;
}
}
}
}
int ans = Integer.MAX_VALUE;
for (int gain = 1; gain <= n; gain++)
ans = Math.min(ans, dp[(1<<n)-1][gain]);
return ans;
}
}
classSolution {
funminimumTime(power: IntArray): Int {
val n = power.size
val dp = Array(1 shl n) { IntArray(n+2) { Int.MAX_VALUE } }
dp[0][1] = 0for (mask in0 until (1 shl n)) {
for (gain in1..n) {
if (dp[mask][gain] ==Int.MAX_VALUE) continuefor (i in0 until n) {
if (mask and (1 shl i) ==0) {
var mana = 0var days = 0while (mana < power[i]) {
mana += gain
days++ }
val nmask = mask or (1 shl i)
if (dp[nmask][gain+1] > dp[mask][gain] + days)
dp[nmask][gain+1] = dp[mask][gain] + days
}
}
}
}
var ans = Int.MAX_VALUE
for (gain in1..n) {
ans = minOf(ans, dp[(1 shl n)-1][gain])
}
return ans
}
}
classSolution:
defminimumTime(self, power: list[int]) -> int:
n: int = len(power)
dp = [[float('inf')] * (n+2) for _ in range(1<<n)]
dp[0][1] =0for mask in range(1<<n):
for gain in range(1, n+1):
if dp[mask][gain] == float('inf'):
continuefor i in range(n):
ifnot (mask & (1<<i)):
mana, days =0, 0while mana < power[i]:
mana += gain
days +=1 nmask = mask | (1<<i)
if dp[nmask][gain+1] > dp[mask][gain] + days:
dp[nmask][gain+1] = dp[mask][gain] + days
ans = float('inf')
for gain in range(1, n+1):
ans = min(ans, dp[(1<<n)-1][gain])
return ans
impl Solution {
pubfnminimum_time(power: Vec<i32>) -> i32 {
let n = power.len();
letmut dp =vec![vec![i32::MAX; n+2]; 1<<n];
dp[0][1] =0;
for mask in0..(1<<n) {
for gain in1..=n {
if dp[mask][gain] ==i32::MAX { continue; }
for i in0..n {
if (mask & (1<<i)) ==0 {
letmut mana =0;
letmut days =0;
while mana < power[i] {
mana += gain asi32;
days +=1;
}
let nmask = mask | (1<<i);
if dp[nmask][gain+1] > dp[mask][gain] + days {
dp[nmask][gain+1] = dp[mask][gain] + days;
}
}
}
}
}
letmut ans =i32::MAX;
for gain in1..=n {
ans = ans.min(dp[(1<<n)-1][gain]);
}
ans
}
}