动态规划大法--Leecode刷题

心情:一如既往,只要困难就凉凉…

题目描述:

有 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 = 315 + 358 + 138 + 181 = 167

思考:

这种题目要怎么能联想到动态规划呢?
首先它不是求某个子集,我觉得一般求某个子集都是回溯,
之后递归我确实也想不到…那就动态规划吧!!!

思路:

1.动态规划一般是dp[i][j] ,这个在这提代表的是什么?
i 和 j 代表的是一个范围,即某个范围的最优解,即在这个范围内戳破气球的最大值。

2.如何求这个范围内的最大值?
从这个范围的值一个个遍历(不包括边界),每次选定的值m,即为这个范围最后一个被戳破的气球!!!那么最后一次戳破气球的值为:

nums[i] x nums[j] x nums[m]

(因为在 i 到 j 之间的气球(除了m)都被戳破了,所以乘的是边界值)
,之后我们并不关心这个k之前 i 到 m 的最大值和 m 到 j 的最大值,因为这个范围比当前小,我们实际上已经在前面已经算出来,所以直接:

dp[i][m]+dp[m][j]+nums[i] x nums[j] x nums[m]

求出这个范围内的最大值。

3.最后注意填充边界,为了方便计算!!

class Solution {
public:

    int maxCoins(vector<int>& nums) {

        int nsize = nums.size();
        nums.insert(nums.begin(),1);
        nums.push_back(1);
        int dp[nsize+2][nsize+2];
        for(int i = 0;i < nsize+2;i++){
            for(int j = 0;j < nsize+2;j++){
                dp[i][j] = 0;
            }
        }

        for(int b = 2;b <= nsize+1;b++){
            for(int i = 0;i <= nsize-b+1;i++){
                int j = i+b;
                for(int m = i+1;m < j;m++){
                    dp[i][j] = max(dp[i][j],dp[i][m]+dp[m][j]+nums[i]*nums[j]*nums[m]);
                }
            }
        }

        return dp[0][nsize+1];
    }

};


未完待续…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值