<p>You are given <code>n</code> balloons, indexed from <code>0</code> to <code>n - 1</code>. Each balloon is painted with a number on it represented by an array <code>nums</code>. You are asked to burst all the balloons.</p>

<p>If you burst the <code>i<sup>th</sup></code> balloon, you will get <code>nums[i - 1] * nums[i] * nums[i + 1]</code> coins. If <code>i - 1</code> or <code>i + 1</code> goes out of bounds of the array, then treat it as if there is a balloon with a <code>1</code> painted on it.</p>

<p>Return <em>the maximum coins you can collect by bursting the balloons wisely</em>.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>

<pre>
<strong>Input:</strong> nums = [3,1,5,8]
<strong>Output:</strong> 167
<strong>Explanation:</strong>
nums = [3,1,5,8] --&gt; [3,5,8] --&gt; [3,8] --&gt; [8] --&gt; []
coins =  3*1*5    +   3*5*8   +  1*3*8  + 1*8*1 = 167</pre>

<p><strong class="example">Example 2:</strong></p>

<pre>
<strong>Input:</strong> nums = [1,5]
<strong>Output:</strong> 10
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>n == nums.length</code></li>
	<li><code>1 &lt;= n &lt;= 300</code></li>
	<li><code>0 &lt;= nums[i] &lt;= 100</code></li>
</ul>

class Solution {
public:

    long int dp[301][301] = {-1};

    // returns left over element to be used for recursion purpose.
    long int calc(vector<int>& nums, int i, int j, int left, int right )
    {

        if( i > j) return 0;
        if( dp[i][j] != -1 )
        {
            return dp[i][j];
        }

        // now this is a contiguous steam.
        // assume each element to be alive.
        long int maxReturn =
            max( left*nums[i]*right + calc(nums, i + 1, j, nums[i], right),
                left*nums[j]*right + calc(nums, i, j - 1, left, nums[j] ) 
            );

        for(int k = i + 1; k < j; k++)
        {
            // if kth element is alive.
            maxReturn = max(maxReturn, 
                (left*nums[k]*right) + calc(nums, i, k-1, left, nums[k])
                    + calc(nums, k + 1, j, nums[k], right) );
        }

        dp[i][j] = maxReturn;
        return maxReturn;
    }

    int maxCoins(vector<int>& nums) {

        // close records
        memset(dp, -1, sizeof(dp));  

        int n = nums.size();

        if( nums.size() == 1) return nums[0];
        else if(nums.size() ==  2) return ( nums[0]*nums[1] + max(nums[0], nums[1]) );

        calc(nums, 0, n-1, 1, 1);

        // return score.
        return dp[0][n-1];
    }
};
11400