leetcode笔记--Burst Balloons

 题目:难度(Hard)

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
Tags:Divide and Conquer,Dynamic Programming

分析:

    设dp[left, right]表示扎破(left,right)范围的气球能获得的最大硬币数(但不包含边界气球),我一开始认为的状态转移方程为dp[left, right] = max(dp[left, right], dp[left, i] + nums[i-1]*nums[i]*nums[i+1] + dp[i, right]),因为题目中告诉我们在计算nums[i]对应的coins数时,是将它与它的两个邻居节点相乘,但仔细分析:dp[left, i]表示扎破(left, i)范围的气球得到的最大coins数,此时剩下的气球是left与i气球(因为dp[left, i]不含边界),同理dp[i, right]最后剩下的气球是i与right气球,即此时剩下的气球是(left,i,right),那么此时i气球获得的coin数就是nums[left]*nums[i]*nums[right]),则状态转移方程为dp[left, right] = max(dp[left, right], dp[left, i] + nums[left]*nums[i]*nums[right] + dp[i, right])其中left<i<right,则dp[left, right] 就计算了扎破所有不包含left,right边界值的气球的coins数。

    按题意应为所给数组增加值为1的首尾元素,设n为新数组的长度,那么dp[0][n-1]即为所求。时间复杂度是O(n^3) ,状态转移方程类似Floyd最短路径算法。

代码实现:

class Solution(object):
    def maxCoins(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        #先给nums两边加上1,注意list的扩展可用“+”运算符,也可用list.extend(list1)方法
        nums = [1] + nums + [1]
        n = len(nums)
        dp = [[0]*n for _ in range(n)]
        for k in range(2, n):
            for left in range(0, n-k):
                right = left + k
                #此时,边界left,right已经确定
                for i in range(left+1, right):#不含边界
                    dp[left][right] = max(dp[left][right], dp[left][i] + nums[left]*nums[i]*nums[right] + dp[i][right])
                    
        return dp[0][n-1]

参考:

   http://blog.csdn.net/xyqzki/article/details/50255345

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值