weekly contest 415。
比賽中能過的代碼,賽後又加了幾個測資,現在又變成 MLE。
不知道會不會被 rejudge 掉。

題目

輸入長度 4 的整數陣列 a,以及長度至少 4的整數陣列 b。

你必需從 b 之中選擇四個索引 i0, i1, i2 和 i3,滿足 i0 < i1 < i2 < i3。
並獲得分數等於 a[0] * b[i0] + a[1] * b[i1] + a[2] * b [i2] + a[3] * b[i3]。

最大得分。

解法

要在 b 之間找四個元素和 a 配對,而且順序有要求,所以要從固定往一個方向找。
此處以 a[0], a[1], a[2], a[3] 的順序配對。

遍歷 b 中每個元素 b[j],嘗試和 a[i] 配對並決定選或不選
不同的選法可能導致 b 和 a 剩餘相同的元素,有重疊的子問題,因此考慮 dp。

定義 dp(i, j):配對 a[i..3] 和 b[j..N-1] 的最大得分,並決定 a[i] 是否和 b[j] 配對。
轉移:dp(i, j) = max(選, 不選)。

  • 選:dp(i+1, j+1)
  • 不選:dp(i, j+1)

base:當 i = 4 時,代表 a 已經配對完,回傳 0;否則當 j = N 時,代表 a 還沒配完,但 b 已經沒了,不合法所以回傳 -inf。

時間複雜度 O(N)。
空間複雜度 O(N)。

class Solution:
    def maxScore(self, a: List[int], b: List[int]) -> int:
        N = len(b)

        @cache
        def dp(i, j): # a[i], b[j]
            if i == 4:
                return 0
            if j == N:
                return -inf
            return max(
                dp(i, j+1), 
                dp(i+1, j+1) + a[i] * b[j]
            )

        ans = dp(0, 0)
        dp.cache_clear() # prevent MLE

        return ans