Leetcode 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 = 3*1*5 + 3*5*8 + 1*3*8 + 1*8*1 = 167

 

思路

 

考虑最后一个戳破的气球,这个气球的位置可以把整个气球数组分成两部分。

注意是最后一个,不是第一个,之前一直没转过弯来。

利用动态规划思路:

 

动态规划数组:

DP[k][h]:nums[k...h]能戳破气球的最大值

递推关系:

取k

则DP[k][h] =

for (m = k+1...h)

max(DP[k][m] + DP[m][h] + nums[k] * nums[m] * nums[h]);

初始值:

需要扩展nums,数组长+2,头和尾分别加入1

DP[k][h]:

当k + 1 = h 或 k = h时,为0;

当k + 2 = h 时,为 nums[k] * nums[k+1] * nums[k+2];

 

 1 public class Solution{
 2     public int maxCoins(int[] nums) {
 3         //DP: the result depends on the last burst balloon, which seprate the array into 2 subarray.
 4         // DP: by adding 1 to head and tail, DP[i,i] = 0 and DP[i,i+2] = num[i] * num[i+1] * num[i+2]
 5         int n = nums.length+2;
 6         int[] newnums = new int[n];
 7         for (int i = 0;i < n - 2; i++){
 8             newnums[i+1] = nums[i];
 9         }
10         newnums[0] = newnums[n - 1] = 1;
11         int[][] DP = new int[n][n];
12         for (int k = 2; k < n; k++){
13             for (int l = 0; l + k < n; l++){
14                 int h = l + k;
15                 for (int m = l + 1; m < h; m++){
16                     DP[l][h] = Math.max(DP[l][h],newnums[l] * newnums[m] * newnums[h] + DP[l][m] + DP[m][h]);
17                 }
18             }
19         }
20         return DP[0][n - 1];
21     }
22 }

 

你可能感兴趣的:(Leetcode 312.戳气球)