Burst Balloons

Description
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:
(1) You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

Example:

Given [3, 1, 5, 8]

Return 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

解题思路:使用逆向思维解决这道题。假设f(i,j)表示炸掉编号为i到j的气球所能获得的最多硬币,先考虑最后炸掉的气球,如果最后炸掉的气球的编号为k,那么f(i,j)= f(i,k)+f(k,j)+ nums[k](i<=k<=j),因为在最后一步k能够取遍i到j的所有可能,但是在上一步比如计算f(i,k)或f(k,j)时,编号k的气球就不能够被选为要炸掉的气球,因此如果这一步要炸掉的气球的编号为k’ 时,k’ 的可能选择为(i<= k’ < k 或k< k ‘< j)。为了统一k的取值,先在这组气球的头和尾加入编号为i-1以及j+1的两个气球,令f’(i-1,j+1)表示炸掉编号区间为(i,j)的气球所能获得的最多硬币。其实也可以这么考虑,只要把f’(i,j)中的i和j号气球当成最后要炸的两个气球,那么在此之前要炸掉在(i+1,j-1)中的所有气球。令在头和尾加入的那两个气球代表的数目为1,f(i,j)=f’(i+1,j-1)=max{f’(i+1,k)+f’(k,j-1)+nums[i+1] * nums[k] * nums[j-1]}(i + 1< k < j - 1)。程序代码如下:

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        vector<vector<int>> dp(nums.size() + 2, vector<int>(nums.size() + 2, 0));
        vector<int> n(nums.size() + 2, 1); //在头和尾加入两个气球后的数组
        for (int i = 0; i < nums.size(); i++)
            n[i + 1] = nums[i];

        for (int len = 2; len <= n.size(); len++) {
            for (int left = 0; left + len - 1 < n.size(); left++) {
                int right = left + len - 1;
                for (int i = left + 1; i < right; i++) {
                    dp[left][right] = max(dp[left][right], n[left] * n[i] * n[right] 
                                          + dp[left][i] + dp[i][right]);
                }
            }
        }

        return dp[0][nums.size() + 1];
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值