Burst Balloons

来源:互联网 发布:pdf编辑软件绿色版 编辑:程序博客网 时间:2024/06/07 10:11

题目:

    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

题目大意:

    给定n个气球,下标为0到n-1。每个气球上都标有一个数字,用数组nums表示。你要射中所有气球。射中第i个气球可以获得nums[left] * nums[i] * nums[right]个积分。这里left和right是与i相邻的下标。射中气球以后,left和right就变成相邻的了。求你可以获得的最大积分数

Note: 
You may imagine nums[-1] = nums[n] = 1. They are not real therefore you can not burst them

  你可以假设nums[-1] = nums[n] = 1. 它们并非真实的因此不可能射中。


思路分析:

  首先我们可以知道已经被射中的气球不会影响现存的气球maxcoin的计算。因此我们可以将分成若干个小问题计算,那我们可以选择先找出射中两个气球时的maxcoin,射中三个气球时的maxcoin,......,射中n个气球时的maxcoin。但是这些问题又是重叠的,因为你在计算射中m 个气球时的maxcoin,要用到m-1个气球时的结果。因此我们可以用分治方法和dp结合起来求解,因为分治和dp都需要将原问题分解成小问题,然后逐一解决;不过分治方法的每个小问题都是不相关的,而dp的子问题则是重叠的。

  我们以最后射中的气球为界限,把数组分为左右两个子区域,然后分别在每个子区域中求解,该气球被射中之前,前后的气球都不会相互影响。可以用一个数组dp[i][j]记忆从下标i到下标j之间的最大coins。


状态传递方程为:

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)范围内所有气球获得的最多积分,不含边界;left与right的跨度从2开始逐渐增大;三重循环依次枚举范围跨度k,左边界left,中点i;右边界right = left + k。

时间复杂度为 O(n^3) , 空间复杂度为 O(n^2)

代码如下:

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];  
    }  
};  












0 0
原创粉丝点击