目标
给你一个 下标从 1 开始的 整数数组 prices ,其中 prices[i] 表示你购买第 i 个水果需要花费的金币数目。
水果超市有如下促销活动:
- 如果你花费 prices[i] 购买了下标为 i 的水果,那么你可以免费获得下标范围在 [i + 1, i + i + 1] 的水果。
注意 ,即使你 可以 免费获得水果 j ,你仍然可以花费 prices[j] 个金币去购买它以获得它的奖励。
请你返回获得所有水果所需要的 最少 金币数。
示例 1:
输入:prices = [3,1,2]
输出:4
解释:
用 prices[0] = 3 个金币购买第 1 个水果,你可以免费获得第 2 个水果。
用 prices[1] = 1 个金币购买第 2 个水果,你可以免费获得第 3 个水果。
免费获得第 3 个水果。
请注意,即使您可以免费获得第 2 个水果作为购买第 1 个水果的奖励,但您购买它是为了获得其奖励,这是更优化的。
示例 2:
输入:prices = [1,10,1,1]
输出:2
解释:
用 prices[0] = 1 个金币购买第 1 个水果,你可以免费获得第 2 个水果。
免费获得第 2 个水果。
用 prices[2] = 1 个金币购买第 3 个水果,你可以免费获得第 4 个水果。
免费获得第 4 个水果。
示例 3:
输入:prices = [26,18,6,12,49,7,45,45]
输出:39
解释:
用 prices[0] = 26 个金币购买第 1 个水果,你可以免费获得第 2 个水果。
免费获得第 2 个水果。
用 prices[2] = 6 个金币购买第 3 个水果,你可以免费获得第 4,5,6(接下来的三个)水果。
免费获得第 4 个水果。
免费获得第 5 个水果。
用 prices[5] = 7 个金币购买第 6 个水果,你可以免费获得第 7 和 第 8 个水果。
免费获得第 7 个水果。
免费获得第 8 个水果。
请注意,即使您可以免费获得第 6 个水果作为购买第 3 个水果的奖励,但您购买它是为了获得其奖励,这是更优化的。
说明:
1 <= prices.length <= 1000
1 <= prices[i] <= 10^5
思路
有 n 个水果,其价格由 prices
表示,当我们以 prices[i]
枚金币购买了第 i + 1 个苹果时,我们可以免费获得下标 [i + 1, i + i + 1]
的 所有 个苹果(当然也可以购买以获得后面的奖励),求获得全部苹果所需的最少硬币。
最直接的想法是记忆化搜索。
代码
/**
* @date 2025-01-24 9:07
*/
public class MinimumCoins2944 {
public int minimumCoins(int[] prices) {
int[] mem = new int[2 * prices.length + 3];
Arrays.fill(mem, Integer.MAX_VALUE);
return dfs(0, prices, mem, 0);
}
public int dfs(int index, int[] prices, int[] mem, int cost) {
int n = prices.length;
if (index >= n) {
return cost;
}
int res = cost + prices[index];
int next = index * 2 + 2;
if (mem[next] == Integer.MAX_VALUE) {
mem[next] = dfs(next, prices, mem, 0);
}
int remainder = mem[next];
if (remainder == 0) {
return res;
}
for (int i = index + 1; i < n && i <= index * 2 + 1; i++) {
if (mem[i] == Integer.MAX_VALUE) {
mem[i] = dfs(i, prices, mem, 0);
}
remainder = Math.min(mem[i], remainder);
}
return res + remainder;
}
}