首页 > 其他 > 详细

312题-戳气球

时间:2020-07-19 11:57:39      阅读:27      评论:0      收藏:0      [点我收藏+]

题目

有n个气球,编号为0到n-1,每个气球上都标有一个数字,这些数字存在数组nums中。现在要求你戳破所有的气球。如果你戳破气球 i ,就可以获得?nums[left] * nums[i] * nums[right]?个硬币。?这里的?left?和?right?代表和?i?相邻的两个气球的序号。注意当你戳破了气球 i 后,气球?left?和气球?right?就变成了相邻的气球。
求所能获得硬币的最大数量。
说明:

  • 你可以假设?nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
  • 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
    示例:
    输入: [3,1,5,8] 输出: 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

解答

这里我打算采用动态规划方法,但是我们发现,当存在四个以上的数的时候,在取掉中间的数时,根据题目要求并不是分为两部分,而是合并到一起形成一个新数组,所以子问题不独立。所以我们需要换一种方式进行状态转移。在区间i-j中,我们寻找最后戳破的气球是得dp[i][j]最大。这里和前面我们选择最先戳破中间k不同。因为k是最后戳破的,所以i到k-1和k+1到j仍然是独立的子问题。状态转移方程为:dp[left][right] = dp[left][i]+dp[i][right]+arr[left] * arr[i] * arr[right]。

代码

class Solution {
    public int maxCoins(int[] nums) {
        int len = nums.length+2;
        int[] arr = new int[len];
        System.arraycopy(nums,0,arr,1,nums.length);
        arr[0] = 1;
        arr[len-1] = 1;
        int[][] dp = new int[len][len];
        for(int gop = 2; gop <len; gop++){
            for(int left = 0; left<len-gop; left++){
                int right = left+gop;
                int conis = 0;
                for(int i = left+1; i < right;i++){
                    conis = Math.max(conis,dp[left][i]+dp[i][right]+arr[left]*arr[i]*arr[right]);
                }
                dp[left][right] = conis;
            }
        }
        return dp[0][len-1];
    }
}

312题-戳气球

原文:https://www.cnblogs.com/jiezao/p/13338540.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!