这题需要用到动态规划的解法,动态规划(记忆化搜索)的关键就是需要寻找子问题和写出状态转移方程。首先寻找子问题,假设dfs(i)表示的是在购买了第i个物品的前提下,求出买第i个物品及以后的物品所需要的最少的金币数。那么举一个例子,由于第一个物品一定需要买,那接下来的问题就是看第二个物品:
1,如果第二个物品购买,那么问题就变成了在购买了第二个物品的前提下,算出购买第二个物品及之后物品的所需最少的金币数。
2,如果第二物品免费,那么第三个物品一定需要买,那么问题就变成了在购买了第三个物品的前提下,算出购买第三个物品及之后物品的所需最少的金币数。
那么状态转移方程就是dfs(i) = min(dfs(i + 1, 2 * i + 1) + prices[i - 1](i - 1是因为从1开始,但是数组的下标从0开始)。以下是我的代码:
Python:
class Solution:
def minimumCoins(self, prices: List[int]) -> int:
n = len(prices)
@cache
def dfs(i):
if i * 2 >= n:
return prices[i - 1]
res = inf
for j in range(i + 1, 2 * i + 2):
res = min(res, dfs(j))
res += prices[i - 1]
return res
return dfs(1)
C++:
class Solution {
public:
int minimumCoins(vector<int>& prices) {
int n = prices.size();
vector<int> memo((n + 1) / 2, -1);
//表示在买了第i个物品的前提下,买第i个物品及以后的物品所需的最少金币数
auto dfs = [&](this auto&&dfs, int i) -> int {
if (i * 2 >= n) {
return prices[i - 1]; //和二叉树一样,先从第一个数作为特例来看
}
auto& res = memo[i];
if (res != -1) {
return res;
}
res = INT_MAX;
for (int j = i + 1; j <= 2 * i + 1; j ++) {
res = min(res, dfs(j));
}
res += prices[i - 1];
return res;
};
return dfs(1);
}
};
加油!!!!!