题目:312
题意:有N个气球,要求你戳破所有的气球,每戳破一个,你可以获得nums[left]*nums[i]*nums[right]个硬币,注意戳破一个气球后相邻顺序会改变。求戳破所有气球所能获得的最大硬币数量
题解:
DP + 分治,主要是想分解为重叠子问题,但是如果简单考虑一下,先随机选择一个气球,然后求左右两边的两个子问题,但是左右两边并不是独立的子问题,即左边的顺序会影响右边的计算结果。所有我们可以继续想一下,如何将左右两边划分为两个独立的子问题,于是我们可以得到如下结论:
left 和 right 相互独立 <=> k 点为对于N的分割时,最后一个被踩破的气球。
这样的话我们就可以整体DP+局部分治进行求解了。
代码:
class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = nums.size(); //新构造数组的大小
vector<int> arr(nums);
arr.insert(arr.begin(), 1);
arr.insert(arr.end(), 1);
vector< vector<int> > dp(n + 2, vector<int>(n + 2, 0)); //边界dp[i][i+1] == 0
//状态转移方程
for (int len = 2; len < n + 2; ++len)
for (int i = 0; i < n + 2 - len; ++i)
for (int k = i + 1; k < i + len; ++k)
dp[i][i + len] = max(dp[i][i + len], dp[i][k] + dp[k][i + len] + arr[i] * arr[k] * arr[i + len]);
return dp[0][n + 1];
}
};