- Total Accepted: 23535
- Total Submissions: 56077
- Difficulty: Hard
- Contributors: Admin
题目:
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[n] = 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
翻译:
给定n个气球,从0到n-1。 每个气球都涂上了一个由数组num表示的数字。 你被要求爆破所有的气球。 如果你爆了气球,我会得到数[num] [num] [num] [num] [right]硬币。 这里左右是i的相邻索引。 在爆发之后,左边和右边变得相邻。
找出您可以通过明智地爆破气球来收集的最大硬币。
注意:
(1)你可以想象nums [-1] = nums [n] = 1。他们不是真的,所以你不能爆发他们。
(2)0≤n≤500,0≤nums [i]≤100
例:
给定[3,1,5,8]
返回167
nums = [3,1,5,8] - > [3,5,8] - > [3,8] - > [8] - > []
硬币= 3 * 1 * 5 + 3 * 5 * 8 + 1 * 3 * 8 + 1 * 8 * 1 = 167
解题思路 :
1,开始考虑递归,即 每一次 找当前数列最大的三个数乘积然后加上去掉中间数之后数列的最大段乘积和 综合记为 sum[i], 比较n个数的sum[i] 最大者即为 所求 , 复杂度递归公式为 T(n) = n T(n-1) + O(n) , 复杂度为O(!n) 超时,遂转换思路。
2. 参考了网上的解析, 思路很巧妙, 设一个=二维的数组, v[i][j] 表示nums[i]~nums[j] 之间的最大段乘积和, 从单个单元开始,
第一次 长度为1 , 范围从 nums[0]到 nums[n] , v[i][i] 表示 nums[i-1] * nums[i] * nums[i+1];
第二次 长度为2 , 范围 从 nums[0] 到 nums[n-1] , v[i][i+1] 表示 从nums[i] 到 nums[i+1] 的段乘积和的最大值。
……
第n次 ,长度为n , 完成循环后 返回 v[1][n] 即为所求。
代码展示:
#include<iostream>
#include<vector>
using namespace std;
class Solution {
public:
int maxCoins(vector<int>& nums) {
int N = nums.size();
nums.insert(nums.begin(),1);
nums.insert(nums.end(),1);
//v[i][j] 表示 nums[i] 到 nums[j] 之间的最大乘积和
vector<vector<int> > v(N+2,vector<int>(N+2,0));
//len 代表当前每一个单元的长度 ,即j - i 的 长度
for(int len = 1; len <= N;len++) {
//start从 1 开始 到 最后一段len单元的起始位置
for(int start = 1; start<= N-len+1;start++) {
//best 表示当前 nums[start] 到 nums[end] 的最大乘机和,
//end 则是当前段单元的末尾位置
int best = 0, end = start + len -1;
for(int i = start; i <= end;i++) {
// temp 代表 nums[start] 到 nums[end]之间 以nums[i] 为最后一个中间点的乘积和
int temp = v[start][i-1] + v[i+1][end] + nums[start-1] * nums[i] * nums[end+1];
if(temp > best) best = temp;
}
v[start][end] = best;
}
}
return v[1][N];
}
};
int main() {
int arr[] = {3, 1, 5, 8};
vector<int> v(arr,arr+4);
Solution s;
cout << s.maxCoins(v) <<endl;
}
题目状态: