312. Burst Balloons

探讨了一个有趣的问题——如何通过智慧地爆破一系列编号并带有数值的气球来获得最大分数。利用动态规划方法解决了该问题,并给出了具体实现的C++代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.

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

Example:

Given [3, 1, 5, 8]

Return 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


刚学过分治算法,所以思考如何使用分治,能想出的方法时间复杂度都太大,不能实现。通过参考solution,分析如下:

分治和动态规划都需要将原问题分解成小问题,然后逐一解决;不过分治方法的每个小问题都是不相关的,而动态规划的子问题则是重叠的。如果直接按照任取k的方法得到的子问题都是重叠的 ,比如对于[a1,a2,a3,a4,a5,a6,......,an],将分割成两个子整体,分割点为k,则得到 N1 = [a1,a2,a3,....,a(k-1)], N2 = [a(k+1),a(k+2),.....,an]。这里分割点k的意义是踩破了第k个气球。于是把整体分成了两部分,但是k气球破了之后,a(k-1)和a(k+1)会变成相邻的,如果此时踩a(k-1)或者a(k+1),则都会收到另一个子整体的影响,所以关键的问题在于确定k。整体的分割需要保证各个整体在后面的计算中要保持相互独立性。

当k点为对于整体N的游戏时,最后一个被踩破的气球时,N1和N2相互独立。那么k点被踩破之前,N1和N2的气球都不会相互影响,于是成功构造子问题。

状态传递方程是:

dp[left][right] = max{dp[left][right] , nums[left] * nums[i] * nums[right]  +  nums[left] * nums[i]  +  nums[i] * nums[right]};

dp[left][right]代表第left和第right之间位置的气球的maxcoin

class Solution {
public:
    int maxCoins(vector<int>& nums) 
    {
        int arr[nums.size()+2];  
          
        for(int i=1;i<nums.size()+1;++i)arr[i] = nums[i-1];  
        arr[0] = arr[nums.size()+1] = 1;  
          
        int dp[nums.size()+2][nums.size()+2]={};  
        int n = nums.size()+2;  
          
        for(int k=2;k<n;++k)  
        {  
            for(int left = 0;left<n-k;++left)
            {  
                int right = left + k;  
                for(int i=left+1;i< right; ++i)  
                {  
                    dp[left][right] = max(dp[left][right],arr[left]*arr[i]*arr[right] + dp[left][i] + dp[i][right]);  
                }  
            }      
        }  
        return dp[0][n-1];  
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值