Burst Balloons | LeetCode

来源:互联网 发布:合并音乐的软件 编辑:程序博客网 时间:2024/05/21 18:17

这题一看到就想起消消乐的游戏,每次消除后其他的马上就重新挨近。一开始想到可能需要用DP,但是无从下手,找不到相似独立的子问题,因为一旦你找到一个i burst, i-1和i+1就重新排布,相邻。也就是说,两边的重新合一起,并不独立。

回顾下之前解决的一道关于股票交易的题,里面涉及到一个cooldown的状态,可以参考一下这个题的解决思路。这道题当时是通过分析最后一次操作状态和前一次操作状态上的关系。这里我们可以从最后一次burst重新考虑这个题。如果i是最后burst的,那么在这之前0~i-1,i+1~n-1这两个区间的气球都已经被消除了,而且。。。最重要的是,由于i是最后被消除的,所以左右两个区间的过程是完全被分开的,也就是说,我们找到了子问题。这里我们看一下

max(left) + left(左边左后被消除) * nums[i] * right(右边最后别消除) + max(right)


最后,对于上面这个公式枚举每一个i, 同样左右两个区间也需要枚举,不断的划分到更小的空间。需要注意的是,位于两端的数由于nums[-1] = nums[n+1] = 1, 而且如果存在0,是可以直接去除的,因为不会带来任何的coins。


编程思路:1.首先去除里面包含的0,然后扩充大小,首尾添加元素1,代表-1,n+1位。

2.使用一个二维数组,记录已left和right之间的元素能够获得的最大coins数。

3.left从0开始到n-1,(扩充后应该是n-2),right应该是从left出发不同间隔的值。注意,left和right都是作为边界。

4.使用公式:coins[left][right] = max(coins[left][right], coins[left] [j] * nums[j] * coins[j][right])

5.最后逐步扩展到以0,n-1为边界的coins,直接返回。


代码如下:

static bool NoCoins(int a){
        return a==0;
    }
    int maxCoins(vector<int>& nums) {
        int res=0;
        if(nums.size()==0)
            return 0;
        //去除零的值
        nums.erase(remove_if(nums.begin(),nums.end(),NoCoins),nums.end());
        nums.resize(nums.size()+2);
        copy(nums.begin(),nums.end()-2,nums.begin()+1);
        //两端为1
        nums[0]=nums[nums.size()-1]=1;
        int n = nums.size();
        int dp[n][n] = {};
        
        for(int i=2;i<n;++i){
            //最外层循环是枚举left和right所有的间隔
            for(int left=0;left<n-i;++left){
                int right = left+i;
                for (int j = left + 1; j < right; ++j){
                    //left和right 分别为左右两部分最后被burst的位置边界,这个内层循环做的事情就是枚举left和right直接最后被burst气球所有带
                    //来的最大,很显然从left+1到right-1
                     dp[left][right] = max(dp[left][right],nums[left] * nums[j] * nums[right] + dp[left][j] + dp[j][right]);
                }
            }
        }
        return dp[0][n-1];
    }

0 0
原创粉丝点击