自上而下
戳气球会导致左右邻居的移动,因此将问题转化为添加气球
helper(i, j)
表示在i~j
这个开区间内添加气球,之所以开区间是因为左右区间设置为边界外,那里的气球是不能戳的,可以考虑到。
然后寻找这个区间添加后值最大的气球,对左右两边继续进行添加,对于每个区间,都会遍历每个值,然后对左右两边进行递归,从而求出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { public: int maxCoins(vector<int>& nums) { vector<int> val(nums.size() + 2, 1); vector<vector<int>> memo(nums.size() + 2, vector<int>(nums.size() + 2, -1)); for(int i = 0; i < nums.size(); ++i) val[i + 1] = nums[i]; return helper(0, nums.size() + 1, memo, val); } private: int helper(int lo, int hi, vector<vector<int>>& memo, vector<int>& val) { if(lo >= hi - 1) return 0; if(memo[lo][hi] != -1) return memo[lo][hi]; for(int i = lo + 1; i < hi; ++i) { auto pro = val[lo] * val[i] * val[hi]; pro += helper(lo, i, memo, val) + helper(i, hi, memo, val); memo[lo][hi] = max(memo[lo][hi], pro); } return memo[lo][hi]; } };
|
自下而上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class Solution { public: int maxCoins(vector<int>& nums) { vector<int> val(nums.size() + 2, 1); vector<vector<int>> memo(nums.size() + 2, vector<int>(nums.size() + 2, 0)); for(int i = 0; i < nums.size(); ++i) val[i + 1] = nums[i]; for(int i = nums.size() - 1; i >= 0; --i) { for(int j = i + 2; j < nums.size() + 2; ++j) { for(int k = i + 1; k < j; ++k) { auto pro = val[i] * val[k] * val[j]; pro += memo[i][k] + memo[k][j]; memo[i][j] = max(memo[i][j], pro); } } } return memo[0][nums.size() + 1]; } };
|