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

思路

解法有backtrack和dp两种,首先还是来分析题目。

这题的要素有:n 个气球,从0到n-1编号,每个气球都标记了一个硬币数字。戳爆其中一个会得到指定的coings,与相邻的两个数字的乘积是所获得的硬币数。那么如何确定戳爆顺序使得获得的硬币数目最大?难点在于不同的戳爆顺序会相互影响。

从最后戳爆的气球位置入手,如果最后戳爆的气球是位置i上的气球,那么可以肯定的是在它之前的 0~i-1 位置上的气球肯定被戳爆了,i+1到n-1位置上的气球也被戳爆了。递归遍历所有的i即可。

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;  // 这里一直用n++是因为要忽视iNums的0,这样n最后不一定等于iNum的长度 int[][] memo = new int[n][n]
return burst(memo, nums, 0, n - 1); // 从1到n-1位置上搜索,即left+1~right,之所以n-1是因为上面的n++使得n到了末尾1的后一位
} public int burst(int[][] memo, int[] nums, int left, int right) {
if (left + 1 == right) return 0;  // 如果left+1==right,因为是从left+1到right-1处遍历的。遍历结束,直接返回
if (memo[left][right] > 0) return memo[left][right];  // 如果已计算过,则不需再次计算
int ans = 0;
for (int i = left + 1; i < right; ++i) // 初始从left+1到right-1,对应起来正好是iNums中的0~n-1
ans = Math.max(ans, nums[left] * nums[i] * nums[right]
+ burst(memo, nums, left, i) + burst(memo, nums, i, right));
memo[left][right] = ans;
return ans;
}

DP解法如下:

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]; // k表示计算步长,从right=left+2开始。因为i从left+1到right-1遍历,所以一开始只计算left和right之间只隔了一位的情况
for (int k = 2; k < n; ++k)
for (int left = 0; left < n - k; ++left) {
int right = left + k;
for (int i = left + 1; i < right; ++i)  // 在子问题dp[left][right]下,遍历每个可能的最后引爆的气球,以求出子问题的最优解
dp[left][right] = Math.max(dp[left][right],
nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right]);  // 左边界是left,右边界是right
} return dp[0][n - 1];
}

LeetCode312. Burst Balloons的更多相关文章

  1. [LeetCode] Burst Balloons (Medium)

    Burst Balloons (Medium) 这题没有做出来. 自己的思路停留在暴力的解法, 时间复杂度很高: 初始化maxCount = 0. 对于当前长度为k的数组nums, 从0到k - 1逐 ...

  2. 动态规划-Burst Balloons

    Burst Balloons Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it ...

  3. LeetCode 312. Burst Balloons(戳气球)

    参考:LeetCode 312. Burst Balloons(戳气球) java代码如下 class Solution { //参考:https://blog.csdn.net/jmspan/art ...

  4. LN : leetcode 312 Burst Balloons

    lc 312 Burst Balloons 312 Burst Balloons Given n balloons, indexed from 0 to n-1. Each balloon is pa ...

  5. 贪心:leetcode 870. Advantage Shuffle、134. Gas Station、452. Minimum Number of Arrows to Burst Balloons、316. Remove Duplicate Letters

    870. Advantage Shuffle 思路:A数组的最大值大于B的最大值,就拿这个A跟B比较:如果不大于,就拿最小值跟B比较 A可以改变顺序,但B的顺序不能改变,只能通过容器来获得由大到小的顺 ...

  6. 【LeetCode】452. Minimum Number of Arrows to Burst Balloons 解题报告(Python)

    [LeetCode]452. Minimum Number of Arrows to Burst Balloons 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https ...

  7. [Swift]LeetCode312. 戳气球 | Burst Balloons

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

  8. [LeetCode] Minimum Number of Arrows to Burst Balloons 最少数量的箭引爆气球

    There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided ...

  9. [LeetCode] Burst Balloons 打气球游戏

    Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by ...

随机推荐

  1. Zabbix3.4.5部署安装(二)

    一.部署环境 一)系统环境: [root@Node3 ~]# cat /etc/redhat-release //查看系统版本 CentOS Linux release (Core) [root@No ...

  2. linux内核设计与实现第七周读书笔记

    第七章 链接 链接(linking)是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储并执行.链接可以执行于编译时(compile time),也就是在源代 ...

  3. 二次封装bootstrap-table及功能优化

    /** * 设置bootstrat-table * @param params */ function setBootstrapTable (target, params) { // 默认设置表格内容 ...

  4. 题解【bzoj3529 [SDOI2014]数表】

    Description \(T\) 组询问,定义 \(F(n)=\sum\limits_{d|n}d\).每次给出 \(n,m,a\) 求 \[\sum\limits_{i=1,j=1,F(\gcd( ...

  5. 「Linux+Django」uwsgi服务启动(start)停止(stop)重新装载(reload)

    转自:http://blog.51cto.com/12482328/2087535?cid=702003 1. 添加uwsgi相关文件 在之前的文章跟讲到过centos中搭建nginx+uwsgi+f ...

  6. Hbuider制作app升级包的简单办法 (升级官方提供的案例)

    源文档:http://ask.dcloud.net.cn/question/11795 http://ask.dcloud.net.cn/article/199 一.生成移动App资源升级包 5+应用 ...

  7. sessionStorage和localStorage的使用

    不管是sessionStorage,还是localStorage,可使用的API都相同,常用的有如下几个(以localStorage为例): 保存数据:localStorage.setItem(key ...

  8. git分支管理图

  9. Spring 源码学习(3) —— 增加属性注册编辑器

    创建一个实体类UserManager: /** * @filename: UserManager.java * @desc 增加属性编辑器功能测试实体类 * @author: Wang Chinda ...

  10. Maven项目Eclipse启动时报错: java.lang.ClassNotFoundException: org.springframework.web.util.IntrospectorCleanupListener

    Eclipse中启动Maven项目时报如下错误: 严重: Error configuring application listener of class org.springframework.web ...