zoukankan      html  css  js  c++  java
  • AcWing 322. 消木块 区间dp+分治

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int N=210;
    int t,n;
    int col[N],A[N],len[N],dp[N][N][N]; 
    //dp[i][j][k]代表消除第 i~j 块且区间最右边留下了 k 个与 j 颜色相同的方块的最大价值
    int solv(int l,int r,int last) {
        //如果左右端点相同了,那么就直接消除 
        if(l==r) 
            return (len[r]+last)*(len[r]+last);
        //如果之前搜过了,直接调用 
        if(dp[l][r][last]) 
            return dp[l][r][last];//记忆化
        //将 r~last 合并并消除,因为后面被消除,所以不存在与 r-1 颜色相同的
        //不存在与r-1颜色相同是因为,从原始数组的左右区间开始往里面递归的
        //再看下面的递推式子,会发现,r~las合并之后,后面就不会存在与r-1颜色相同的 
        dp[l][r][last]=solv(l,r-1,0)+(len[r]+last)*(len[r]+last);
        for(int i=l; i+1<=r-1; i++)
            if(A[i]==A[r])
                //消除 i+1~r-1 后合并 r~last 并删除 l~i 
                //分治,区间两边分开,先把右边的算完,那么再往右边的就会和左边的区间接上 
                dp[l][r][last]=max(dp[l][r][last],solv(l,i,len[r]+last)+solv(i+1,r-1,0));
        return dp[l][r][last];
    }
    int main() {
        scanf("%d",&t);
        for(int cases=1; cases<=t; cases++) {
            memset(col,0,sizeof col);
            memset(len,0,sizeof len);
            memset(A,0,sizeof A);
            memset(dp,0,sizeof dp);
            scanf("%d",&n);
            for(int i=1; i<=n; i++) 
                scanf("%d",&col[i]);
            int cnt=0;
            for(int i=1; i<=n; i++) {
                if(col[i]!=col[i-1]) 
                    A[++cnt]=col[i],len[cnt]=1;
                else 
                    //从当前位置开始,往后有几块连续和她相同 
                    len[cnt]++;
            }
            printf("Case %d: %d
    ",cases,solv(1,cnt,0));
        }
        return 0;
    }
    
    
    
  • 相关阅读:
    雷林鹏分享:XML to HTML
    雷林鹏分享:XML DOM
    雷林鹏分享:XML 编码
    雷林鹏分享: XML CDATA
    雷林鹏分享:服务器上的 XML
    雷林鹏分享:XML 注意事项
    雷林鹏分享:现实生活中的 XML
    雷林鹏分享:XML 相关技术
    雷林鹏分享:XML
    Android 系统架构图
  • 原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12604557.html
Copyright © 2011-2022 走看看