1. 程式人生 > >【LeetCode & 劍指offer刷題】動態規劃與貪婪法題14:Burst Balloons

【LeetCode & 劍指offer刷題】動態規劃與貪婪法題14:Burst Balloons

【LeetCode & 劍指offer 刷題筆記】目錄(持續更新中...)

Burst Balloons

Given   n   balloons, indexed from   0   to   n-1 . Each balloon is painted with a number on it represented by array   nums
. You are asked to burst all the balloons. If the you burst balloon  i you will get nums[left] * nums[i] * nums[right]  coins. Here   left and   right   are adjacent indices of   i . After the burst, the
  left   and   right   then becomes adjacent. Find the maximum coins you can collect by bursting the balloons wisely. Note:
  • You may imagine nums[-1] = nums[n] = 1 .
    They are not real therefore you can not burst them.
  • 0 ≤  n  ≤ 500, 0 ≤  nums[i]  ≤ 100
Example: Input: [3,1,5,8] Output: 167 Explanation: 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
C++   /* 問題:打氣球遊戲 方法:動態規劃 dp[i][j]表示打爆區間[i,j]中的所有氣球能得到的最多金幣 dp[i][j] = max(dp[i][j], nums[i - 1]*nums[k]*nums[j + 1] + dp[i][k - 1] + dp[k + 1][j]) i k j  遍歷區間, 遍歷氣球,在 區間[i,j]中k氣球最後打爆的情況,使最後能得到最多金幣   我們其實只是更新了 dp 陣列的右上三角區域,我們最終要返回的值存在 dp[1][n] 中,其中 n 是兩端新增 1 之前陣列 nums 的個數   例: [3, 1, 5, 8],得到的dp陣列如下: 0    0    0    0    0    0 0    3    30   159  167  0 0    0    15   135  159  0 0    0    0     40    48   0 0    0    0     0      40   0 0    0    0     0      0    0 */ class Solution { public :     int maxCoins ( vector < int >& nums )     {         if ( nums . empty ()) return 0 ;                     int n = nums . size ();         nums . insert ( nums . begin (), 1 ); // 首部填充 0         nums . push_back ( 1 ); // 尾部填充 0,首尾填充後,原nums中數的索引區間為[1,n]         vector < vector < int >> dp ( n + 2 , vector < int >( n + 2 )); // 構建 dp 陣列                 for ( int len = 1 ; len <= n ; len ++) // 區間長度(先算小區間,再算大區間,從小問題算到大問題)         {             for ( int left = 1 ; left <= n - len + 1 ; left ++) // 左端點座標 ,left =1~             {                 int right = left + len - 1 ; // 右端點座標 ,right = len~n (在[1,n]範圍left和right構成滑動窗)                 for ( int k = left ; k <= right ; k ++) // 打爆的氣球位置 , k = left~right                 {                     dp[left][right] = max(dp[left][right],                     nums[left-1]*nums[k]*nums[right+1] + dp[left][k-1] + dp[k+1][right]); // 後面一項表示 [left, right] 區間中 k氣球最後打爆的情況,故最後需要加上nums[left-1]*nums[k]*nums[right+1]                 }             }         }         return dp [ 1 ][ n ];  //dp[1][n]與 nums[0]和nums[n+1]關聯,[1,n]區間對應原陣列區間的數     } };