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. BZOJ4070 [Apio2015]雅加达的摩天楼 【分块 + 最短路】

    题目链接 BZOJ4070 题解 考虑暴力建图,将每个\(B_i\)向其能到的点连边,复杂度\(O(\sum \frac{n}{p_i})\),当\(p\)比较小时不适用 考虑优化建图,每个\(dog ...

  2. 【bzoj4559】成绩比较

    Portal -->bzoj4559 补档计划 ​  借这题补个档--拉格朗日插值 ​​  插值的话大概就是有一个\(n-1\)次多项式\(A(x)\),你只知道它在\(n\)处的点值,分别是\ ...

  3. [转载]DataView详解

    表示用于排序.筛选.搜索.编辑和导航的 DataTable 的可绑定数据的自定义视图. DataView的功能类似于数据库的视图,他是数据源DataTable的封装对象,可以对数据源进行排序.搜索.过 ...

  4. 图像GIF格式介绍

    1 图像GIF格式工作原理 GIF是用于压缩具有单调颜色和清晰细节的图像(如线状图.徽标或带文字的插图)的标准格式. GIF(Graphics InterchangeFormat)的原义是“图像互换格 ...

  5. 树莓派apt-get下载网速太慢

    因为学校有ipv6的原因,当我想用ipv4的时候用apt-get发现特别慢.找了很久终于找到了解决方案: Add -o Acquire::ForceIPv4=true when running apt ...

  6. 转--snmp如何被tr069替代

    Form:本期话题:技术点详解---新型网管理念TR-069 一. 带内网管与带外网管 网络设备是一种资产,资产往往都需要进行管理,网络设备也不例外,网络设备的作用是网络互联,网络应用是一种实时交互性 ...

  7. PHP函数方法

    补充一个P可以HP的特点函数:动态调用 function t(){ echo "welcome"; } function t2(){ echo "beatch" ...

  8. 2.redis设计与实现--链表

    1.链表节点: 2.链表: 3.总结

  9. Qt undefined reference to ***

    错因:某个类声明了一个函数但是没有定义就直接使用.

  10. 【BZOJ】1901: Zju2112 Dynamic Rankings

    [题意]带修改的查询区间第k小 [算法]树状数组套可持久化线段树 [题解]对于树状数组上的每个节点,维护可持久化权值线段树(节点为权值),从而达到查询前缀和的目的. 对于每次修改,在待修改线段树基础上 ...