LeetCode 312 Burst Balloons 题解

题意简述:给出一排气球(用0到n-1代表),每个气球都有一个分数,打爆一个气球可以获得该气球以及它左右气球的三个分数的乘积,并且打爆之后,左右气球变成相邻。求出打爆所有气球所能获得的分数最大值。
输入:一个vector,表示每个气球的分数
输出:分数的最大值
示例:对于4个气球,分数分别为[3,1,5,8],按气球1、2、0、3的顺序打爆,可以获得最大分数
3*1*5+3*5*8+3*8+8=167。


题解:
采用动态规划求解。
首先对于最左或者最右的气球而言,打爆它只会进行两个分数的乘积。如果设定人为的边界,即在左右两边设置一个虚拟的(不能被打爆)、分数为1的气球,那么处理真实的最左最右气球就会跟中间的气球一样进行三个分数的乘积。

考虑求解左右边界分别为i和j(气球i和气球j不打爆,仅用于计算分数)的区间(i,j)获得分数的最大值(记为 dp(i,j) )。这里采用的dp策略是考虑区间内最后被打爆的气球k,因为打爆其他气球的时候气球k肯定存在,所以气球k实际上将区间(i,j)分为(i,k)和(k,j)两部分,于是打爆区间(i,j)的所有气球可以分为三个步骤完成:

  1. 打爆区间(i,k)的所有气球;
  2. 打爆区间(k,j)的所有气球;
  3. 最后打爆气球k,由于k是区间最后一个气球,因此气球k与气球i和气球j相邻。

由此得到的状态转移方程是

dp(i,j)=max(dp(i,k)+nums[i]nums[k]nums[j]+dp(k,j)),  i<k<j

边界情况是 dp(i,i)=0,dp(i,i+1)=0
根据方程,求解区间长为x的情况需要先求解区间长为1、2、……、x-1的情况,因此中间结果不能用一维数组储存而只能用二维数组;与此同时可以采用递推的方法进行求解。

算法的时间复杂度是 O(n3) ,空间复杂度是 O(n2)

class Solution {
public:
    int maxCoins(vector<int>& nums) {
        // add the border
        nums.push_back(1);
        nums.insert(nums.begin(),1);
        int n = nums.size();

        // initialization
        vector<vector<int>> dp;
        for(int i = 0;i < n; i++) {
            vector<int> temp(n, 0);
            dp.push_back(temp);
        }

        // dp
        for(int len = 2;len < n;len++) {
            for(int i = 0;i < n - len;i++) {
                for(int j = i+1;j < i+len;j++) {
                    int temp = dp[i][j] + nums[i]*nums[j]*nums[i+len] + dp[j][i+len];
                    dp[i][i+len] = max(dp[i][i+len], temp);
                }
            }
        }

        return dp[0][n-1];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值