|
| 1 | +class Solution: |
| 2 | + def solve(self, days): |
| 3 | + # n = len(days) |
| 4 | + # prices = [2, 7, 25] |
| 5 | + # durations = [1, 7, 30] |
| 6 | + # dp = [float("inf")] * (n + 1) |
| 7 | + # # dp[i] 表示截止第 i + 1 天(包括)需要多少钱,因此答案就是 dp[n] |
| 8 | + # dp[0] = 0 |
| 9 | + |
| 10 | + # for i in range(1, n + 1): |
| 11 | + # for j in range(i, n + 1): |
| 12 | + # for price, duration in zip(prices, durations): |
| 13 | + # # [i-1, j-1] 闭区间 -> dp [i,j] -> dp[i-1] |
| 14 | + # if days[j - 1] - days[i - 1] + 1 <= duration: |
| 15 | + # dp[j] = min(dp[j], dp[i - 1] + price) |
| 16 | + # return dp[-1] |
| 17 | + |
| 18 | + # m*n^2 => m*nlogn -> m*n m = 3 n = len(days) |
| 19 | + |
| 20 | + # n = len(days) |
| 21 | + # prices = [2, 7, 25] |
| 22 | + # durations = [1, 7, 30] |
| 23 | + |
| 24 | + # @lru_cache(None) |
| 25 | + # def dp(i): |
| 26 | + # if i >= n: |
| 27 | + # return 0 |
| 28 | + # return min([price + dp(bisect.bisect_left(days, days[i] + duration)) for price, duration in zip(prices, durations)]) |
| 29 | + |
| 30 | + # return dp(0) |
| 31 | + |
| 32 | + # n = len(days) |
| 33 | + # prices = [2, 7, 25] |
| 34 | + # durations = [1, 7, 30] |
| 35 | + # dp = [float("inf")] * (n + 1) |
| 36 | + # # dp[i] 表示截止第 i + 1 天(包括)需要多少钱,因此答案就是 dp[n] |
| 37 | + # dp[0] = 0 |
| 38 | + |
| 39 | + # for i in range(1, n + 1): |
| 40 | + # for j in range(i, n + 1): |
| 41 | + # for price, duration in zip(prices, durations): |
| 42 | + # if days[j - 1] - days[i - 1] + 1 <= duration: |
| 43 | + # dp[j] = min(dp[j], dp[i - 1] + price) |
| 44 | + # elif price == 25: |
| 45 | + # break |
| 46 | + |
| 47 | + # return dp[-1] |
| 48 | + prices = [2, 7, 25] |
| 49 | + durations = [1, 7, 30] |
| 50 | + n = len(days) |
| 51 | + m = len(prices) |
| 52 | + dp = [float("inf")] * (n + 1) |
| 53 | + dp[0] = 0 |
| 54 | + pointers = [0] * m |
| 55 | + # 上面 dp 的问题在于 prices 指针不断回溯,实际上没有必要。因为xxxx(上面的 break),比如上一次 price 为 2 的时候内层(第二层)走到 5(j == 5)了,那么下一次 price 为 2 的时候从 5 开始就行了,前面不用看的,都不满足了。因此可使用一个数组记录指针,并保证指针只前进不回退,这样时间复杂度可减低到 m*n |
| 56 | + for i in range(1, n + 1): |
| 57 | + for j in range(m): |
| 58 | + while days[i - 1] - days[pointers[j]] >= durations[j]: |
| 59 | + pointers[j] += 1 |
| 60 | + dp[i] = min(dp[i], dp[pointers[j]] + prices[j]) |
| 61 | + return dp[-1] |
0 commit comments