您的位置:首页 > 其它

leetcode刷题,总结,记录,备忘 312

2016-01-11 19:48 363 查看
leetcode312Burst Balloons

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: 

(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

这道题对我个人感觉还是很难的,对于分而治之和动态规划的敏感度低,使用起来也很拙计,于是翻遍了各种解答方案,终于有了自己的一点小小的领悟。
首先将原来的数组的头尾分别添加2个值为1的元素,是数组维数变为n+2。之后创建一个空的全为0的二维数组,维数为n+2 x n+2。

这个二维数组用来保存每个小段中的最大硬币数量,比如result[1][5]即代表从第1个灯泡开始直到第5个灯泡这个区间中,最大的硬币数量。之后我们需要定义区间的长度len,和开始结束点位置start和end。最大长度从1开始,遍历到n,起始位置从1开始直到,n
- len + 1为止,结束位置也可以相应的计算出来。此时每次遍历的时候,我们需要求的就是result[start][end]值,然后一步步递推,求出最后的结果result[1]
就是整个区间的最大硬币数量。其实之前的步骤都很好理解,最重要的就是动态规划的递推公式了,如下

result[start][end] = max(result[start][end], result[start][i-1] + result[i+1][end] + nums[start-1]*nums[i]*nums[end+1]);

我一开始就是在这个地方愣住了,不懂什么意思,后来自己琢磨了一番,有了理解。其中i是在start和end之间的,是假设作为最后一个被熄灭的灯泡的位置,然后在start和end之间分别选取每个位置作为最后灯泡灭掉的位置,分别求值,将最大值保存在result[start][end]中,即这段区间硬币最大的数量。此时假设start
= 1, end = 4, i刚好遍历到2,根据递推公式,如果是第2个灯泡最后灭的话,求的硬币数量应该是result[1][1] + result[3][4] + nums[0]*nums[2]*nums[5],看到这里,是不是有点了解了,区间为1-4,第二个灯泡最后灭的话,首先区间1-1的硬币数量,区间3-4的硬币数量,必须加起来,然后由于率先灭了2左右的灯泡,所以最后剩下的左右两边分别是nums[0]和nums[5]与nums[2]的乘积,相加,才是最后灭掉灯泡2的最大硬币数量。之后的就是依次遍历,保留最大值。所以关键看懂一个算法还是需要自己不断去试,去在纸上写写画画才有最深刻的体会,很关键,好吧。

编辑下,忘记贴代码了。。。。

class Solution {
public:
int maxCoins(vector<int>& nums) {
int n = nums.size();
nums.insert(nums.begin(), 1);
nums.insert(nums.end(), 1);

vector<vector<int> > result(nums.size(), vector<int>(nums.size(), 0));

int len, start, end;
for (len = 1; len <= n; ++len)
{
for (start = 1; start <= n - len + 1; ++start)
{
end = start + len - 1;
for (int i = start; i <= end; ++i)
{
result[start][end] = max(result[start][end], result[start][i-1] + result[i+1][end] + nums[start-1]*nums[i]*nums[end+1]);
}
}
}

return result[1]
;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: