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

    int maxCoins(vector<int>& nums) {
        ios::sync_with_stdio(false) ;
        cin.tie(0) ;
        vector<vector<int>> max_coins ;
        // nu folosesc doar juma de matrice, deci cand vreau
        //mat[i][j] , trebuie sa face mat[i][j-i]
        max_coins = vector<vector<int>>(nums.size(), vector<int>()) ;
        for(int i = 0 ; i < nums.size() ; i++)
            max_coins[i] = vector<int>(nums.size()-i, 0) ;
        //AICI TREBUIE SA DECLAR FIECARE RAND CU SIZE-UL FIX, NU POT SA FAU PUSH_BACK
        //PT CA DACA DAU EL INITIAL O SA-SI DECLARE UN SIZE PREA MARE
        for(int window_size = 1 ; window_size <= nums.size() ; window_size++)
            for(int start = 0 ; start + window_size - 1 < nums.size() ; start++){
                int end = start + window_size - 1 ;
                int prev_range = ((start-1 >= 0)? nums[start-1] : 1) ;
                int after_range = ((end+1 < nums.size())? nums[end+1] : 1) ;
                for(int pop_last = start ; pop_last <= end ; pop_last++){
                    int popped_left = ((start <= pop_last-1)? max_coins[start][pop_last-1 - start] : 0);
                    int popped_right = ((pop_last+1 <= end)? max_coins[pop_last+1][end - (pop_last+1)] : 0) ;
                    max_coins[start][end - start] = 
                        std::max(max_coins[start][end - start],
                            prev_range*nums[pop_last]*after_range + 
                            popped_left + 
                            popped_right
                        );
                }
            }
        return max_coins[0][nums.size()-1] ;
    }
};
11300