546. Remove Boxes

546Remove Boxes

Given several boxes with different colors represented by different positive numbers. 
You may experience several rounds to remove boxes until there is no box left. Each time you can choose some continuous boxes with the same color (composed of k boxes, k >= 1), remove them and get k*k points.
Find the maximum points you can get.

Example 1:
Input: 

[1, 3, 2, 2, 2, 3, 4, 3, 1]
Output:
23
Explanation: 
[1, 3, 2, 2, 2, 3, 4, 3, 1] 
----> [1, 3, 3, 4, 3, 1] (3*3=9 points) 
----> [1, 3, 3, 3, 1] (1*1=1 points) 
----> [1, 1] (3*3=9 points) 
----> [] (2*2=4 points)

Note: The number of boxes n would not exceed 100.


1、这个题用DFS硬解,会超时:

class Solution {
public:
    int removeBoxes(vector<int>& boxes)
    {
        ret = 0;
        DFS(boxes, 0);
        return ret;
    }
private:
    int ret;
    void DFS(vector<int>& boxes, int point)
    {
        if (boxes.empty())
        {
            ret = max(ret, point);
            return;
        }
        
        int i = 0, j = 0;
        while (j < boxes.size())
        {
            while (j < boxes.size() && boxes[j] == boxes[i])
                j++;
            
            vector<int> tmp = boxes;
            tmp.erase(tmp.begin() + i, tmp.begin() + j);
            DFS(tmp, point + pow(j - i, 2));
            i = j;
        }
    }
};

2、网上找的动态规划方法,必须记住!

dp数组应该是一个三维数组dp[i][j][k],表示区间[i, j]中能获得的最大积分,当boxes[i]左边有k个数字跟boxes[i]连续相等,
那么我们的目标就是要求dp[0][n-1][0]了,
而且我们也能推出dp[i][i][k] = (1+k) * (1+k)这个等式。
那么我们来推导重现关系,对于dp[i][j][k],如果我们移除boxes[i],那么我们得到(1+k)*(1+k) + dp[i+1][j][0]。
对于上面提到的那种情况,当[i, j]中某个位置m,有boxes[i] == boxes[m]时,我们也应该考虑先移除[i+1,m-1]这部分,我们得到积分dp[i+1][m-1][0],然后再处理剩下的部分,得到积分dp[m][j][k+1],这里k加1点原因是,移除了中间的部分后,原本和boxes[m]不相邻的boxes[i]现在相邻了,又因为二者值相同,所以k应该加1,因为k的定义就是左边相等的数字的个数。

class Solution {
public:
    int removeBoxes(vector<int>& boxes)
    {
        int n = boxes.size();
        int dp[100][100][100] = {0};
        return helper(boxes, 0, n - 1, 0, dp);
    }
    int helper(vector<int>& boxes, int i, int j, int k, int dp[100][100][100])
    {
        if (j < i) return 0;
        if (dp[i][j][k] > 0) return dp[i][j][k];    //有点记忆话搜索的感觉
        int res = (1 + k) * (1 + k) + helper(boxes, i + 1, j, 0, dp);   //拆除i和之前的一样的
        for (int m = i + 1; m <= j; ++m)
        {
            if (boxes[m] == boxes[i])
            {
                res = max(res, helper(boxes, i + 1, m - 1, 0, dp) + helper(boxes, m, j, k + 1, dp));
            }
        }
        return dp[i][j][k] = res;
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值