动态规划求解扎气球得金币游戏

1. 问题

  给定n个气球,编号从0至n-1,每个气球上写了一个数字,这些数字存放在数组nums中。现在你来扎破所有的气球。当扎破第i个气球时,可以得到的金币个数为nums[left] * nums[i] * nums[right],这里的left和right指的是第i个气球相邻气球的编号。(当扎破一个气球后,原来它左右侧的气球将成为相邻气球)。
  求通过扎气球可以获得的最大金币数量。

说明:

(1) 可以假想nums[-1] = nums[n] = 1,当然,它们仅仅是为了方便假想出来的,并不能够被扎破
(2) 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

2. 图解分析

这里写图片描述

3. 代码

int maxCoins(vector<int>& nums) {
    int n = nums.size();
    nums.insert(nums.begin(), 1); //左侧添1
    nums.push_back(1); //右侧添1
    vector<vector<int>> dp(nums.size(), vector<int>(nums.size(), 0)); //初始化DP数组

    /* 从问题规模从1逐步放大到n */
    for (int len = 1; len <= n; ++len) {
        /* 滑动窗口的方式挪动求解范围的两侧 */
        for (int left = 1; left <= n - len + 1; ++left) {
            int right = left + len - 1;
            /* 在[left, right]确定的滑动窗口中求解 */
            for (int k = left; k <= right; ++k) {
                dp[left][right] = max(
                    dp[left][right],
                    nums[left-1]*nums[k]*nums[right+1]
                        + dp[left][k-1]
                        + dp[k+1][right]
                );
            }
        }

    }

    return dp[1][n];
}

问题URL:https://leetcode.com/problems/burst-balloons/

猜你喜欢

转载自blog.csdn.net/solomonlangrui/article/details/52917680