• 546. 移除盒子(难)


    题目

    546. 移除盒子

    我的思路

    一种想法是深搜递归。选择当前盒子中任意一个,删除相同颜色并且连续的盒子后将剩余的盒子继续递归选择并删除。这样直接计算的话复杂度太高了,需要记忆化存储搜索过程来降低复杂度。还没想到合适的。。

    另一种想法是动态规划。n个盒子的最大积分和由n-1,n-2,...1个盒子的积分决定:也似乎不方便

    还有一种是反向思维,去掉盒子的逆过程是插入盒子??


    参考官方题解,整理一下思路:

    设置指针l,r
    如果f(l,r)表示l到r区间内的最大积分,那么f(l,r)经过如下递推而得:去除从l位置开始的连续相同元素,假设k个,那么f(l+k-1,r)+k*k;找到第一个与l位置元素相同但不相邻的元素,假设位置在j,那么f(j+1,r)+f(l+k,j-1)+(k+1)^2;再找第二个与l位置元素相同但不相邻的元素,这时需要考虑这个不相邻的元素是否与前面找到的不相邻元素相邻,该元素是直接与l元素块作为邻居去掉还是加上第一个不相邻元素三个一起作为邻居去掉。。。似乎并不便于分析
    如果多一个参数f(l,r,k)表示考虑上l左侧有k个与l元素相同的元素,l到r区间内的最大积分。这样可以方便的进行递归分析,f(l,r,k)计算如下:f(l+1,r,0)+(k+1)^2;找到l右侧第p个与l元素相同的位置j,f(jp,r,k+1)+f(l+1,jp-1,0)。以上多个表达式的最大值,可以用三维数组记忆化递归路径。如此递归终止条件是:f(n,n,k) = (k+1)^2;或者f(n,n-1,0) = 0;

    我的实现

    class Solution {
    public:
        vector<vector<vector<int>>> memoryMatrix;
        int dps(int l,int r,int k,vector<int>& boxes){
            if(memoryMatrix[l][r][k]!=0)return memoryMatrix[l][r][k];
            if(l==r){
                //cout<<l<<"	"<<r<<"	"<<(k+1)*(k+1)<<endl;
                memoryMatrix[l][r][k] = (k+1)*(k+1);
                return  memoryMatrix[l][r][k];
            }else if(l>r){
                return 0;
            }else{
                if(boxes[l+1]==boxes[l]){
                    memoryMatrix[l][r][k] = dps(l+1,r,k+1,boxes); 
                    return memoryMatrix[l][r][k];
                }else{
                    int j = l+2;
                    int tempmax = 0;
                    while(j<=r){
                        
                        if(boxes[j]==boxes[l]){
                            //cout<<l<<"=="<<j<<endl;
                            tempmax = max(tempmax,dps(j,r,k+1,boxes)+dps(l+1,j-1,0,boxes));
                        }
                        j++;
                    }
                    memoryMatrix[l][r][k] =  max(tempmax,dps(l,l,k,boxes)+dps(l+1,r,0,boxes));
                    //if(l==1&&r==7)cout<<memoryMatrix[l][r][k]<<"====
    ";
                    return memoryMatrix[l][r][k];
                }
            }
        }
        int removeBoxes(vector<int>& boxes) {
            int numBoxes = boxes.size();
            for(int i=0;i<=numBoxes;i++){
                vector<vector<int>> temp1;
                
                for(int i=0;i<=numBoxes;i++){
                    vector<int> temp2(numBoxes+1,0);
                    temp1.push_back(temp2);
                }
                memoryMatrix.push_back(temp1);
            }
            //dps(0,numBoxes-1,0,boxes);
            
            //return 0;
            return dps(0,numBoxes-1,0,boxes);
    
    
    
    
        }
    };
    /*
    一种想法是深搜递归。选择当前盒子中任意一个,删除相同颜色并且连续的盒子后将剩余的盒子继续递归选择并删除。这样直接计算的话复杂度太高了,需要记忆化存储搜索过程来降低复杂度。还没想到合适的。。
    
    另一种想法是动态规划。n个盒子的最大积分和由n-1,n-2,...1个盒子的积分决定:也似乎不方便
    
    还有一种是反向思维,去掉盒子的逆过程是插入盒子??
    
    
    参考官方题解,整理一下思路:
    
    设置指针l,r
    如果f(l,r)表示l到r区间内的最大积分,那么f(l,r)经过如下递推而得:去除从l位置开始的连续相同元素,假设k个,那么f(l+k-1,r)+k*k;找到第一个与l位置元素相同但不相邻的元素,假设位置在j,那么f(j+1,r)+f(l+k,j-1)+(k+1)^2;再找第二个与l位置元素相同但不相邻的元素,这时需要考虑这个不相邻的元素是否与前面找到的不相邻元素相邻,该元素是直接与l元素块作为邻居去掉还是加上第一个不相邻元素三个一起作为邻居去掉。。。似乎并不便于分析
    如果多一个参数f(l,r,k)表示考虑上l左侧有k个与l元素相同的元素,l到r区间内的最大积分。这样可以方便的进行递归分析,f(l,r,k)计算如下:f(l+1,r,0)+(k+1)^2;找到l右侧第p个与l元素相同的位置j,f(jp,r,k+1)+f(l+1,jp-1,0)。以上多个表达式的最大值,可以用三维数组记忆化递归路径。如此递归终止条件是:f(n,n,k) = (k+1)^2;或者f(n,n-1,0) = 0;
    
    */

    拓展学习

  • 相关阅读:
    USB描述符(转)
    (转)Linux设备驱动之HID驱动 源码分析
    Linux USB 鼠标驱动程序详解(转)
    (转)linux如何获取鼠标相对位置信息
    从零写一个编译器(四):语法分析之构造有限状态自动机
    从零写一个编译器(三):语法分析之几个基础数据结构
    从零写一个编译器(二):语法分析之前置知识
    从零写一个编译器(一):输入系统和词法分析
    自底向上语法分析
    递归下降和LL(1)语法分析
  • 原文地址:https://www.cnblogs.com/BoysCryToo/p/13508685.html
Copyright © 2020-2023  润新知