LeetCode Week8: Remove boxes

来源:互联网 发布:python 元组 分数 编辑:程序博客网 时间:2024/05/20 18:53

这周完成的题目是关于动态规划和DFS的题目:Remove boxes。

Remove 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.

分析

题目要求从左到右依次消除方块,颜色相同的k个方块可以一起消除,可以得到k*k分,求如何消除能够得到最高分。

分析:其实这道题是借助了题解才能想的出来,这也说明自己的积累还是不够==

假设对于串132223431,我们用一个三维数组rec[l][r][same_len],来记录从l到r的序列中,当第r个元素有same_len个相同的后缀元素时,消除这个序列能够得到的最高分。

假设dps函数能够找到从l到r的消除方块的最高分,对于dfs,我们假设其处理流程为:

  • 初始时找从0到8(串长度为8)dps(0,8,0),对于最右元素,其相同后缀为0,所以初始化时rec[0][8][0] = dps(0,7,0) + 1*1(因为只能消除1);
  • 对于dps(0,7,0) 重复上述操作,直到r=4,此时后三位的元素都是相同的,所以遍历完这三个元素后,r=2,same_len = 2,那么rec[0][4][2] = dps(0,2,0) +3*3(消除3个相同颜色方块,再消除前面剩余方块);
  • 一直递归深搜下去,直到遍历完整个序列;
  • 递归开始上升:
    • 对于dps(0,6,0),我们可以发现,从最左开始遍历,我们可以遍历到boxes[1] = boxes[r],也就是说,我们现在存在2种解法,一种是刚刚计算的,一个一个消除(碰到已经有的连续的就把连续的统一消除),一种是去构造:让这两个隔得远的元素能够在别的方块被消除后聚到一起,所以dps(0,6,0) = min(rec[0][6][0], dps(0,1,2)+dps(2,5,0),对应到我们的串中,就是先消除3个2,然后对于13序列,最右元素的相同后缀长度为1,所以消除变成了1+2*2+3*3 = 14;
    • 所以对于所有的元素,从l到r遍历时都会经历这样的两个阶段
      • 初始:rec[l][r][same_len] = dps(l,r-1)+(same_len+1)*(same_len+1);
      • 更新:如果从l到r序列中,第i个元素与r元素相等,那么就需要更新rec[l][r][same_len] = min(rec[l][r][same_len],dps(l,i,same_len+1)+dps(i+1,r-1,0));

我的解答

整个过程的代码如下图所示:

class Solution {private:public:    /* l: 最左位置     * r: 最右位置     * same_len : 在r后面且与r相同的元素的长度     * rec: 记录从l到r的后缀长度为same_len时的消除值     * boxes: 所有盒子的颜色值     * 返回最终的最大的盒子值     */    int dfs(int l, int r, int same_len, int rec[100][100][100], vector<int>& boxes){        if(l>r) return 0;        // 已经遍历过不需要再遍历        if(rec[l][r][same_len] > 0)             return rec[l][r][same_len];        while(r>l && boxes[r] == boxes[r-1]){            r--;            same_len++;        }        rec[l][r][same_len] = (same_len+1)*(same_len+1) + dfs(l,r-1,0,rec,boxes);        for(int i = l; i < r;i++)            if(boxes[i] == boxes[r])                // 如果发现这个值跟最右的值相等,存在两种可能                // 先消除最右的元素及其后缀元素的长度                // 消除当前值和最右值中间的元素再消除相同的元素值和当前元素值前面的元素                rec[l][r][same_len] = max(rec[l][r][same_len], dfs(l,i,same_len+1,rec,boxes)+dfs(i+1,r-1,0,rec,boxes));         return rec[l][r][same_len];    }    int removeBoxes(vector<int>& boxes) {        int rec[100][100][100] = {0};        return dfs(0,boxes.size()-1,0,rec,boxes);    }};
0 0
原创粉丝点击