[LeetCode]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 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

题目大意:

给定n个气球,下标为0到n-1。每个气球上都标有一个数字,用数组nums表示。你被要求扎破所有气球。扎破第i个气球可以获得nums[left] * nums[i] * nums[right]枚硬币。这里left和right是与i相邻的下标。扎破气球以后,left和right就变成相邻的了。

寻找最优策略下可以获得的硬币数。

注意:

(1) 你可以假设nums[-1] = nums[n] = 1. 它们并非真实的因此不能扎破。

(2) 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

解题思路:

动态规划(Dynamic Programming)

时间复杂度O(n ^ 3)

参考peisi的答案:https://leetcode.com/discuss/72216/share-some-analysis-and-explanations

以最后被爆破的气球m为界限,把数组分为左右两个子区域

状态转移方程:

dp[l][r] = max(dp[l][r], nums[l] * nums[m] * nums[r] + dp[l][m] + dp[m][r])

dp[l][r]表示扎破(l, r)范围内所有气球获得的最大硬币数,不含边界;

l与r的跨度k从2开始逐渐增大;

三重循环依次枚举范围跨度k,左边界l,中点m;右边界r = l + k;

状态转移方程在形式上有点类似于Floyd最短路算法。

Java代码:

public class Solution {
    public int maxCoins(int[] iNums) {
        int[] nums = new int[iNums.length + 2];
        int n = 1;
        for (int x : iNums) if (x > 0) nums[n++] = x;
        nums[0] = nums[n++] = 1;

        int[][] dp = new int[n][n];
        for (int k = 2; k < n; ++k)
            for (int l = 0; l < n - k; ++l) {
                int r = l + k;
                for (int m = l + 1; m < r; ++m)
                    dp[l][r] = Math.max(dp[l][r], 
                        nums[l] * nums[m] * nums[r] + dp[l][m] + dp[m][r]);
            }
    
        return dp[0][n - 1];
    }
}

 

本文链接:http://bookshadow.com/weblog/2015/11/30/leetcode-burst-balloons/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。

如果您喜欢这篇博文,欢迎您捐赠书影博客: ,查看支付宝二维码

Pingbacks已关闭。

评论
  1. 奶爸网 naiba.im 奶爸网 naiba.im 发布于 2015年12月2日 08:31 #

    顶你一个~~~~

  2. 大王驮我去巡山 大王驮我去巡山 发布于 2016年1月1日 21:00 #

    backtracking + memo-ization毫无悬念地超时了。。。
    nums[l] * nums[m] * nums[r] + dp[l][m] + dp[m][r]略微难理解。。
    博主的文章一直写得不错,谢谢

  3. cpd0101 cpd0101 发布于 2016年3月6日 22:31 #

    以最后被爆破的气球m为界限,把数组分为左右两个子区域

  4. 大睿-SCTrojan 大睿-SCTrojan 发布于 2016年3月14日 03:56 #

    这句话是关键,我开始一直在想m到底是啥来着,想了好久也没猜出来。。

  5. 在线疯狂 在线疯狂 发布于 2016年3月14日 22:19 #

    感谢补充!:D

张贴您的评论