Java实现 LeetCode 312 戳气球

312. 戳气球

有 n 个气球,编号为0 到 n-1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

现在要求你戳破所有的气球。每当你戳破一个气球 i 时,你可以获得 nums[left] * nums[i] * nums[right] 个硬币。 这里的 left 和 right 代表和 i 相邻的两个气球的序号。注意当你戳破了气球 i 后,气球 left 和气球 right 就变成了相邻的气球。

求所能获得硬币的最大数量。

说明:

你可以假设 nums[-1] = nums[n] = 1,但注意它们不是真实存在的所以并不能被戳破。
0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100
示例:

输入: [3,1,5,8]
输出: 167
解释: nums = [3,1,5,8] --> [3,5,8] --> [3,8] --> [8] --> []
coins = 315 + 358 + 138 + 181 = 167

class Solution {
      private int[][] dp;

    public void fill(int[] nums, int from, int to) {
        int max = 0, maxLeft, maxRight, result;
        //假设第i个气球是最后被戳破的
        for (int i = from; i <= to; i++) {
            maxLeft = dp[from][i - 1];
            maxRight = dp[i + 1][to];
            result = maxLeft + maxRight + nums[from - 1] * nums[i] * nums[to + 1];
            max = result > max ? result : max;
        }
        dp[from][to] = max;
    }

    public int maxCoins(int[] nums) {
        int length = nums.length;
        dp = new int[length + 2][length + 2];
        for (int i = length + 1; i >= 0; i--) {
            Arrays.fill(dp[i], 0);
        }
        
        int[] expandNums = new int[length + 2];
        expandNums[0] = expandNums[length + 1] = 1;
        System.arraycopy(nums, 0, expandNums, 1, length);
        
        for (int span = 0; span < length; span++) {
            //fill a diagonal
            //assume the span (of array of length i) is i-1
            for (int from = length - span; from > 0; from--) {
                //fill dp[from][from + span]
                fill(expandNums, from, from + span);
            }
        }
        return dp[1][length];
    }
}
原文地址:https://www.cnblogs.com/a1439775520/p/13075887.html