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

题目理解:

给定一个数组,每一次消除其中一个数字num,消除这个数字的得分,是num与其相邻两个数的乘积

解题思路:

动态规划算法。动态规划问题解的最终形态是自底向上解决问题,我做这个题目的时候只实现到了使用递归+记录的低级形式,但是好处是比较好理解。

如果将整个数组分成两个部分来分治,那么两个部分的解会有关联,因为某一部分边界值计算会用到另一部分的边界值。

因此考虑将数组分为三个部分,左边是一个子数组left,中间是一个数字num,右边是一个子数组right,计算num是最后消除的数的时候,最大的得分是多少。

借助分治,我们可以得到right部分的最优解和left部分的最优解,当left和right中所有的数字都已经消除完毕时,再消除num的得分就是num,因此合并的方式就是result[left]+num+result[right]

如果left中只剩下一个数n,那么得分就是n;如果left中一个数也没有,那么得分就是0

在得到了一个子数组的最优之后,我们将这个最优解记录下来,如果之后还遇到求这个子数组最优解的情况,我们就可以直接用了

class Solution {
    int[] nums;
    int len;
    Map<String, Integer> map = new HashMap<>();

    public int helper(int left, int right){
        int leftBound = left - 1, rightBound = right + 1;
        String str = left + " " + right;
        if(map.containsKey(str))
            return map.get(str);
        if(left > right)
            return 0;
        int res = 0;
        int leftValue = leftBound < 0 ? 1 : nums[leftBound];
        int rightValue = rightBound >= len ? 1 : nums[rightBound];
        for(int i = left; i <= right; i++){
            int leftRes = helper(left, i - 1);
            int rightRes = helper(i + 1, right);
            res = Math.max(res, leftRes + rightRes + nums[i] * leftValue * rightValue);
        }
        //System.out.println(left + " " + right + " " + leftBound + " " + rightBound + " " + res);
        map.put(str, res);
        return res;
    }

    public int maxCoins(int[] nums) {
        this.nums = nums;
        len = nums.length;
        return helper(0, len - 1);
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值