[leetcode] Burst Balloons
2016-02-25 00:00
351 查看
题目描述:
Given
Each balloon is painted with a number on it represented by array
are asked to burst all the balloons. If the you burst balloon
get
adjacent indices of
becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
(1) You may imagine
can not burst them.
(2) 0 ≤
100
Example:
Given
Return
这题的分治思想并不是很直观,因为divide并不是可以一次性地将一个问题分成两个子问题。(我们应该跳出分治一定是分成两个子问题的这种思维定势),而且conquer的时候也不是常规意义的合并,而是取max。
不过直接采用递归的思想去思考,还是比较容易的。但写算法的话就可以用DP了,递归会超时。
dp(i, j) = max{dp(i, k) + dp(k, j) + nums[i]*nums[k}*nums[j]}, k = [i+1, j-1]
dp(i,j)表示数组arr[i,j]对应的该问题的最优解,其中arr[i]和arr[j]都是不能被burst的气球。
而上面的递归式右边max大括号里的表达式表示,最后一个burst的气球是第k个时,我们能够得到的最多的硬币的数目。
另外,这里填充dp的方式也不是常规的i从0到n-1,j也从0到n-1,而是按照j与i之间的间隔逐渐增大的对角线的方式进行填充。至于为什么要用这种方式填充,上面的递推式给出了答案。我们要求dp(i,j)时,一定要预先知道i和j之间的任意区间的dp值,而我们如果采用i从0到n-1,j也从0到n-1或者由大到小的迭代方式都没法满足这个条件,即如果i从小到大,j也从小到大,那么求dp(i,j)时,需要用到dp(i,k)和dp(k,j),i<k<h,其中dp(i,k)会在它之前得到,但dp(k,j)就还没计算到,因为k>i。
而经过观察我们发现,dp(i,k)和dp(k,j)的下标区间长度一定比dp(i,j)要小,所以我们可以采用区间长度由小到大的方式进行填充dp数组。
问题想明白了的话,其实代码还是相对比较容易写的。
Given
nballoons, indexed from
0to
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
iyou will
get
nums[left] * nums[i] * nums[right]coins. Here
leftand
rightare
adjacent indices of
i. After the burst, the
leftand
rightthen
becomes adjacent.
Find the maximum coins you can collect by bursting the balloons wisely.
Note:
(1) You may imagine
nums[-1] = nums = 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
这题的分治思想并不是很直观,因为divide并不是可以一次性地将一个问题分成两个子问题。(我们应该跳出分治一定是分成两个子问题的这种思维定势),而且conquer的时候也不是常规意义的合并,而是取max。
不过直接采用递归的思想去思考,还是比较容易的。但写算法的话就可以用DP了,递归会超时。
dp(i, j) = max{dp(i, k) + dp(k, j) + nums[i]*nums[k}*nums[j]}, k = [i+1, j-1]
dp(i,j)表示数组arr[i,j]对应的该问题的最优解,其中arr[i]和arr[j]都是不能被burst的气球。
而上面的递归式右边max大括号里的表达式表示,最后一个burst的气球是第k个时,我们能够得到的最多的硬币的数目。
另外,这里填充dp的方式也不是常规的i从0到n-1,j也从0到n-1,而是按照j与i之间的间隔逐渐增大的对角线的方式进行填充。至于为什么要用这种方式填充,上面的递推式给出了答案。我们要求dp(i,j)时,一定要预先知道i和j之间的任意区间的dp值,而我们如果采用i从0到n-1,j也从0到n-1或者由大到小的迭代方式都没法满足这个条件,即如果i从小到大,j也从小到大,那么求dp(i,j)时,需要用到dp(i,k)和dp(k,j),i<k<h,其中dp(i,k)会在它之前得到,但dp(k,j)就还没计算到,因为k>i。
而经过观察我们发现,dp(i,k)和dp(k,j)的下标区间长度一定比dp(i,j)要小,所以我们可以采用区间长度由小到大的方式进行填充dp数组。
问题想明白了的话,其实代码还是相对比较容易写的。
class Solution { public: int maxCoins(vector<int>& nums) { if(0 == nums.size()) return 0; nums.insert(nums.begin(), 1); nums.push_back(1); int n = nums.size(); vector<int> col(n, 0); vector<vector<int>> dp(n, col); for(int len = 2; len < n; ++len) { for(int i = 0; i < n-len; ++i) { int ret = 0; for(int k = i+1; k < i+len; ++k) { int tmp = dp[i][k] + dp[k][i+len] + nums[i]*nums[k]*nums[i+len]; if(tmp > ret) ret = tmp; } dp[i][i+len] = ret; } } return dp[0][n-1]; } };
相关文章推荐
- Java9积极解决Linux中的GTK GUI难题
- 【分享】高手Java核心技术学习笔记
- Linux下同步模式、异步模式、阻塞调用、非阻塞调用总结
- 【分享】 Windows 各种计时函数总结
- VIEWGOOD(远古)校园网多媒体系统的搭建
- 微信红包随机算法的实现
- oracle导入、导出
- HTTPClient模块的HttpGet和HttpPost
- 遍历Map的方式: Map.Entry 和 Map.entrySet()
- eclipse 中使用Git
- QSqlQuery::value: not positioned on a valid record
- VS2008中文乱码
- flexible
- mysql-5.7.11-winx64 免安装版(MySQL ZIP Archive版)配置及密码问题处理
- 检测点1.1
- 检测点2.1
- mysql递归查询treeview
- Oracle Connect By Prior(递归查询)简洁实例
- Java printf用法
- Yii 中Criteria常用方法(转+原)