312. Burst Balloons 戳气球
Title
有 n 個氣球,編號為0 到 n-1,每個氣球上都標有一個數字,這些數字存在數組 nums 中。
現在要求你戳破所有的氣球。如果你戳破氣球 i ,就可以獲得 nums[left] * nums[i] * nums[right] 個硬幣。 這里的 left 和 right 代表和 i 相鄰的兩個氣球的序號。注意當你戳破了氣球 i 后,氣球 left 和氣球 right 就變成了相鄰的氣球。
求所能獲得硬幣的最大數量。
說明:
- 你可以假設 nums[-1] = nums[n] = 1,但注意它們不是真實存在的所以并不能被戳破。
- 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
示例:
輸入: [3,1,5,8] 輸出: 167 解釋: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []coins = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167動態規劃
為了方便處理,我們對 nums 數組稍作處理,將其兩邊各加上題目中假設存在的 nums[?1] 和 nums[n] ,并保存在 val 數組中,即 val[i]=nums[i?1] 。之所以這樣處理是為了處理 nums[?1] ,防止下標越界。
逆向思維,戳氣球會導致兩個氣球從不相鄰變成相鄰,很難處理,我們倒過來看,將全過程看作是每次添加一個氣球。
令 dp[i][j] 表示填滿開區間 (i,j) 能得到的最多硬幣數,那么邊界條件是 i≥j?1,此時有 dp[i][j]=0。
可以寫出狀態轉移方程:
dp[i][j]={maxk=i+1j?1val[i]×val[k]×val[j]+dp[i][k]+dp[k][j],i<j?10,i>=j?1dp[i][j]=\begin{cases} max^{j-1}_{k=i+1}val[i]×val[k]×val[j]+dp[i][k]+dp[k][j],\quad i<j-1 \\\\ 0,\quad i>=j-1 \end{cases}dp[i][j]=??????maxk=i+1j?1?val[i]×val[k]×val[j]+dp[i][k]+dp[k][j],i<j?10,i>=j?1?
最終答案即為 dp[0][n+1]。實現時要注意到動態規劃的次序。
Code
def maxCoins(self, nums: List[int]) -> int:length, val = len(nums), [1] + nums + [1]dp = [[0] * (length + 2) for _ in range(length + 2)]for i in range(length - 1, -1, -1):for j in range(i + 2, length + 2):for k in range(i + 1, j):total = val[i] * val[k] * val[j]total += dp[i][k] + dp[k][j]dp[i][j] = max(dp[i][j], total)return dp[0][length + 1]復雜度分析
時間復雜度:O(n3),其中 n 是氣球數量。狀態數為 n2,狀態轉移復雜度為 O(n),最終復雜度為 O(n2×n)=O(n3)。
空間復雜度:O(n2),其中 n 是氣球數量。
總結
以上是生活随笔為你收集整理的312. Burst Balloons 戳气球的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 6.Vue Class 与 Style
- 下一篇: 2019年第十届蓝桥杯 - 省赛 - C