mirror of
https://github.com/ShusenTang/LeetCode.git
synced 2024-09-02 14:20:01 +00:00
Create 312. Burst Balloons.md
This commit is contained in:
parent
9264814b88
commit
f96ad7ab1a
47
solutions/312. Burst Balloons.md
Normal file
47
solutions/312. Burst Balloons.md
Normal file
@ -0,0 +1,47 @@
|
||||
# [312. Burst Balloons](https://leetcode.com/problems/burst-balloons/)
|
||||
|
||||
# 思路、区间动归
|
||||
题目介绍了一种打气球的游戏,每个气球上面都有一个数字,每次打爆一个气球,得到的金币数是被打爆的气球及其两边的气球上的三个数字之积,如果旁边没有气球了,则按1算。求将所有气球打爆能得到的最多金币总数。
|
||||
|
||||
如果我们将首尾各插入一个数字为1的气球,那么首尾这两个气球是不能打的,这样这题就和[Poj 1651:Multiplication Puzzle](http://bailian.openjudge.cn/practice/1651/)基本一样了。那么在这种情况下该怎么打气球呢?
|
||||
|
||||
(首尾各插入一个数字为1的气球后,)有以下几种情况:
|
||||
1. 如果不到三个气球,那么得到的金币总数显然为0;
|
||||
2. 如果刚好三个气球,那么得到的金币总数也可以直接算出来就是中间气球上的数字;
|
||||
3. 如果大于三个气球,假设我们将第k(i < k < j)个气球作为分界线,那么先按照最优策略打爆k之前的剩下第一个气球,再按照最优策略打爆k之后的剩下最后一个气球,那么此时还剩下三个气球:首尾加上第k个,最后将第k个气球打爆,结束。
|
||||
|
||||
如果dp[i][j]表示第i个气球到第j个气球的最优打法所获得的金币总数,那么上面第3中情况即代表了转移方程:
|
||||
```
|
||||
for all k in [i+1, ..., j-1]:
|
||||
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]);
|
||||
```
|
||||
|
||||
**需要注意的是上述的`dp[i][k]`和`dp[k][j]`都代表的是最优策略,而因为`i < k`所以在最外层循环i是从最大值往0递减循环
|
||||
而不是从0开始递增循环!**
|
||||
|
||||
# C++
|
||||
``` C++
|
||||
class Solution {
|
||||
public:
|
||||
int maxCoins(vector<int>& nums) {
|
||||
nums.insert(nums.begin(), 1);
|
||||
nums.push_back(1);
|
||||
|
||||
int N = nums.size();
|
||||
vector<vector<int>>dp(N, vector<int>(N, 0));
|
||||
// 注意这里i是从最大值递减循环!
|
||||
for(int i = N - 1; i >= 0; i--){
|
||||
for(int j = i + 1; j < N; j++){
|
||||
// if(j == i + 1) dp[i][j] = 0;
|
||||
// else if(j == i + 2) dp[i][j] = nums[i] * nums[i+1] * nums[i+2];
|
||||
// else{
|
||||
for(int k = i+1; k < j; k++)
|
||||
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k][j] + nums[i]*nums[k]*nums[j]);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
return dp[0][N-1];
|
||||
}
|
||||
};
|
||||
```
|
Loading…
Reference in New Issue
Block a user