题目描述
有n个气球,编号为0到n-1,每个气球都有一个分数,存在nums数组中。每次吹气球i可以得到的分数为 nums[left] * nums[i] * nums[right],left和right分别表示i气球相邻的两个气球。当i气球被吹爆后,其左右两气球即为相邻。要求吹爆所有气球,得到最多的分数。
样例
输入:[4, 1, 5, 10]
输出:270
解释:
nums = [4, 1, 5, 10] 吹爆 1, 得分 4 * 1 * 5 = 20
nums = [4, 5, 10] 吹爆 5, 得分 4 * 5 * 10 = 200
nums = [4, 10] 吹爆 4, 得分 1 * 4 * 10 = 40
nums = [10] 吹爆 10, 得分 1 * 10 * 1 = 10
总得分 20 + 200 + 40 + 10 = 270
输入:[3,1,5]
输出:35
解释:
nums = [3, 1, 5] 吹爆 1, 得分 3 * 1 * 5 = 15
nums = [3, 5] 吹爆 3, 得分 1 * 3 * 5 = 15
nums = [5] 吹爆 5, 得分 1 * 5 * 1 = 5
总得分 15 + 15 + 5 = 35
题解
记忆化搜索
public class Solution {
public int maxCoins(int[] nums) {
int n = nums.length;
int [][]dp = new int [n+2][n+2];
int [][]visit = new int[n+2][n+2];
int [] arr = new int [n+2];
for (int i = 1; i <= n; i++){
arr[i] = nums[i-1];
}
arr[0] = 1;
arr[n+1] = 1;
return search(arr, dp, visit, 1 , n);
}
public int search(int []arr, int [][]dp, int [][]visit, int left, int right) {
if(visit[left][right] == 1)
return dp[left][right];
int res = 0;
for (int k = left; k <= right; ++k) {
int midValue = arr[left - 1] * arr[k] * arr[right + 1];
int leftValue = search(arr, dp, visit, left, k - 1);
int rightValue = search(arr, dp, visit, k + 1, right);
res = Math.max(res, leftValue + midValue + rightValue);
}
visit[left][right] = 1;
dp[left][right] = res;
return res;
}
}