LeetCode: Burst Balloons

来源:互联网 发布:网络黑客电影国产 编辑:程序博客网 时间:2024/06/05 17:18

题目:
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

这道题最粗暴的想法是用深度优先搜索,把每一种可能的踩气球的顺序都遍历一遍,时间复杂度为O(n!),显然会超时,是不可取的。
用分治的思路,把问题分解为小问题求解。分治的一个要点是,分解后的每个小问题之间无重叠,即每个小问题是相互独立不影响彼此的结果的。所以,怎么分成了一个重要的问题。假设分割点为k,其意义为踩破了第k个气球,于是left={nums[0],nums[1],…,num[k-1]},right={nums[k+1],nums[k+2],…,nums[n-1]),这样,left中的nums[k-1]和right中的nums[k+1]就变成了邻居,两个小问题就有可能互相影响结果,除非k是最后一个被踩的气球编号。所以,设k为最后一个被踩的气球。这样,就将问题转化为无重叠的小问题。
具体算法(其实有点动态规划的思想):重新建立一个边界为1,中间元素为nums中所有元素的数组array,所以其长度n=nums.size()+2。d[x][y]表示扎破(x,y)范围内的所有气球获得的最大硬币数(不包括x和y),则:
d[x][y]=max(d[x][y], array[x] * array[k] * array[y] + d[x][k] + d[k][y])
x与y的跨度m从2开始逐渐增加到n-1,三重循环依次枚举范围跨度m,左边界x(右边界y=x+m),分割点k。Accepted的代码:

class Solution {public:    int maxCoins(vector<int>& nums) {        //构建一个包含边界的数组array        vector<int> array;        array.push_back(1);        for(int i=0;i<nums.size();i++) array.push_back(nums[i]);        array.push_back(1);        int n=array.size();        int d[n][n]={};        //三重循环        for(int m=2;m<n;m++)        {            for(int x=0;x<n-m;x++)            {                int y=x+m;                for(int k=x+1;k<y;k++)                    d[x][y]=max(d[x][y],  array[x]*array[k]*array[y]+d[x][k]+d[k][y]);            }        }        return d[0][n-1];    }};
0 0
原创粉丝点击