Burst Balloons 168

Question

Given n balloons, indexed from 0 to n-1. Each balloon is painted with a number on it represented by array nums. You are asked to burst all the balloons. If the you burst balloon i you will get nums[left] nums[i] nums[right] coins. Here left and right are adjacent indices of i. After the burst, the left and right then becomes adjacent.

Find the maximum coins you can collect by bursting the balloons wisely.

  • You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them.
  • 0 ≤ n ≤ 500, 0 ≤ nums[i] ≤ 100

Example

Given [4, 1, 5, 10]

Return 270

nums = [4, 1, 5, 10] burst 1, get coins 4 1 5 = 20

nums = [4, 5, 10] burst 5, get coins 4 5 10 = 200

nums = [4, 10] burst 4, get coins 1 4 10 = 40

nums = [10] burst 10, get coins 1 10 1 = 10

Total coins 20 + 200 + 40 + 10 = 270

Solution

用线段DP+记忆化搜索的方法。DP[i][j]表示i-j个气球能取得的最大值。

初始化:在nums左右两边各增加1个dummy balloon,使其值为1。这是为了计算方便,在乘的时候不用考虑边界情况。

状态函数:假设某一个气球k是最后打爆的,则其最大值为k左边气球最大值+k右边气球最大值+打爆k的值。遍历数组,记录每个元素成为k时能取的最大值,然后在其中找到最大的值即可。

当某个元素k最后打爆时,其值为array[左边界-1] array[右边界+1] array[k]。然后搜索左边界到k-1的最大值和k+1到右边界的最大值。

代码如下:

public class Solution {
    /**
     * @param nums a list of integer
     * @return an integer, maximum coins
     */
    public int maxCoins(int[] nums) {
        // Write your code here
        if(nums == null || nums.length == 0){
            return 0;
        }

        int n = nums.length;
        int[] array = new int[n + 2];
        for(int i = 1; i <= n; i++){
            array[i] = nums[i - 1];
        }
        array[0] = 1;
        array[n + 1] = 1;

        int[][] dp = new int[n + 2][n + 2];
        boolean[][] visit = new boolean[n + 2][n + 2];

        return search(1, n, array, dp, visit);
    }

    private int search(int start, int end, int[] array, int[][] dp, boolean[][] visit){
        if(visit[start][end]){
            return dp[start][end];
        }

        int max = 0;
        for(int k = start; k <= end; k++){
            int midValue = array[start - 1] * array[k] * array[end + 1];
            int left = search(start, k - 1, array, dp, visit);
            int right = search(k + 1, end, array, dp, visit);
            max = Math.max(max, midValue + left + right);
        }
        visit[start][end] = true;
        dp[start][end] = max;
        return dp[start][end];
    }
}

results matching ""

    No results matching ""