【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]区间对应原数组区间的数
    }
};
 

猜你喜欢

转载自www.cnblogs.com/wikiwen/p/10229393.html