Friday, May 6, 2016

LeetCode Q312: Burst Balloon (hard)

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


Solution:
Use DP. Please read this post for a wondering explanation and thinking process. The key of using DP in this question is to think entire process of bursting balloon reversely that the first balloon we deem as bursted is actually the last balloon we burst in practice.


class Solution {
public:
int helper(vector<vector<int> >& T, vector<int>& nums, int p ,int q){
if(p+1==q)
return 0;
if(T[p][q]>0)
return T[p][q];
int maxv = 0;
for(int i=p+1; i<q; i++){
int v1 = helper(T, nums, p, i);
int v2 = helper(T, nums, i, q);
int v3 = nums[p]*nums[i]*nums[q];
maxv = max(maxv, v1+v2+v3);
}
T[p][q]=maxv;
return maxv;
}
int maxCoins(vector<int>& nums) {
vector<int> myNums(nums.size()+2);
int n=1;
for(int x:nums) if(x>0) myNums[n++]=x;
myNums[0]=myNums[n++]=1;
vector<vector<int> > T(n, vector<int>(n, 0));
int res = helper(T, myNums, 0, n-1);
return res;
}
};
view raw Q312.cpp hosted with ❤ by GitHub
Non iterative solution:
int maxCoins(vector<int>& nums) {
int n = nums.size();
nums.insert(nums.begin(), 1);
nums.push_back(1);
vector<vector<int> > dp(nums.size(), vector<int>(nums.size() , 0));
for (int len = 1; len <= n; ++len) {
for (int left = 1; left <= n - len + 1; ++left) {
int right = left + len - 1;
for (int k = left; k <= right; ++k) {
dp[left][right] = max(dp[left][right], nums[left - 1] * nums[k] * nums[right + 1] + dp[left][k - 1] + dp[k + 1][right]);
}
}
}
return dp[1][n];
}
view raw Q312-2.cpp hosted with ❤ by GitHub

No comments:

Post a Comment