<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:
/*

[1,3,1,5,8,1]
l = 1 , r = 4
k = 1,  1 is the last balloon to burst
temp = 3 * 1 * 1 + fun(1, 0) + fun(2, 4)

k = 2
temp = 1 * 1 * 1 + fun(1, 1) + fun(3, 4)

k = 4
temp = 8 * 1 * 1 + fun(1, 3) + fun(5, 4)

[1,3,1,5,8,1]
l = 1 , r = 3
k = 1
temp = 3 * 1 * 8 + fun(1, 0) + fun(2, 3)


*/
    int helper(vector<int>& nums, int left, int right, vector<vector<int>>& dp)
    {
        if(left > right)
            return 0;
        if(dp[left][right] != -1)
            return dp[left][right];

        int ans = INT_MIN;
        int temp = 0;

        for(int k = left; k <= right; k++)
        {
            temp = nums[k] * nums[left - 1] * nums[right + 1] + helper(nums, left, k - 1, dp) + helper(nums, k + 1, right, dp);
            ans = max(ans, temp);
        }

        return dp[left][right] = ans;
    }
    int maxCoins(vector<int>& nums)
    {
        nums.push_back(1);
        nums.insert(nums.begin(), 1);

        vector<vector<int>> dp(nums.size() + 1, vector<int> (nums.size() + 1, -1));

        return helper(nums, 1, nums.size() - 2, dp);
    }
};

/*

n balloons from 0 to n - 1
burst ith balloon to get nums[i-1] * nums[i] * nums[i+1]

max coins

iterate over all indices to split into 2 halves and add current coins

1 3 1 5 8 1    3*1*5
1 3 5 8 1      3*5*8
1 3 8 1        1*3*8
1 8 1          1*8*1

for k E [l, r) ; l to r

if I burst k th balloon, assume we already have burst and ans for [l, k) and [k + 1, r)

score = nums[k] * nums[l - 1] * nums[r]


*/
12300