leetcode 困难 —— 戳气球(超详细思路)

题目:
有 n 个气球,编号为 0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。
现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。
求所能获得硬币的最大数量。

题解:
用 dp 求解,这个 dp 思路非常妙

假如存在一组气球 a b c d e f g h i j k,我们要求这个的结果
为了方便计算我们预处理成 1 a b c d e f g h i j k 1
这时候假如我们最后剩下了 e
那么是不是就相当于 [ (1) a b c d (e) 的结果] + [ (e) f g h i j k (1) 的结果] + [ 1 * e * 1 ]

(这样的前提是什么呢,就是因为如果已知 e 是最后剩下的,那么这两段的最优情况是互不干扰的,所以这两个部分加上最后剩下的气球得到的值,就是最优解,所以满足最关键的 每个子问题的决策不能对后面其他未解决的问题产影响,无后效性

那么接下来比如我们看 (e) f g h i j k (1) 这一段
是不是也和最开始的情况一样
假如最后剩下的是 i
相当于 [ (e) f g h (i) ] + [ (i) j k (1) ] + [ (e) * i * (1) ]

由此可以得出可以得出公式
dp [ i ] [ j ] = dp [ i ] [ k - 1 ] + dp [ k + 1 ] [ j ] + val [ i - 1 ] * val [ j + 1 ] * val [ k ]

那么我们就可以开始写代码了,附上

class Solution {
public:
    int dp[305][305];
    int maxCoins(vector<int>& nums) {
        int n = nums.size();
        nums.insert(nums.begin(), 1);
        nums.push_back(1);
        for(int l = 0; l < n; l++) {
            for(int i = 1; i + l <= n; i++) {
                for(int k = i; k <= i + l; k++) {
                    dp[i][i+l] = max(dp[i][i+l], nums[k] * nums[i-1] * nums[i+l+1] + dp[i][k-1] + dp[k+1][i+l]);
                }
            }
        }
        return dp[1][n];
    }
};
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值