zoukankan      html  css  js  c++  java
  • POJ 1390 Blocks(区间DP + 记忆化搜索)

    题意:

    一排带有颜色的砖块,每一个可以消除相同颜色的砖块,每一次可以到块数 k 的平方分数。问怎么消能使分数最大。

    思路:

    1. 此题是结合区间动态规划和记忆化搜索的好题,状态转移方程不太好想,以下思路还是根据黑书上面的解释来的;

    2. dp[i, j, k] 表示区间 [i, j] 并且在区间后面还有长度为 k 的砖块和 j 的颜色一致;

    3. 如果 j 就和后面的 k 个结合则有:dp[i, j-1, 0] + (len[j] + k) ^ 2;

    4. 如果 j 和前面若干段结合,并且前面若干段最后一段是 p,则有:dp[i, p, len[j]+k] + dp[p+1, j-1, 0];

    5. 列出了上述方程式,用线性的方法是无法胜任的,因为 k 无法确定。这时候采取记忆化搜索的办法,从后往前来,问题得到解决;

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 210;
    
    int dp[MAXN][MAXN][MAXN];
    int color[MAXN], len[MAXN], pre[MAXN], table[MAXN], block[MAXN];
    
    int solvedp(int l, int r, int k) {
        if (l > r) 
            return 0;
    
        if (dp[l][r][k] != -1)
            return dp[l][r][k];
        
        if (l == r) {
            return dp[l][r][k] = (len[r]+k)*(len[r]+k);
        }
        int ans;
        ans = solvedp(l, r-1, 0) + (len[r]+k)*(len[r]+k);
    
        for (int i = pre[r]; i >= l; i = pre[i]) {
            if (color[i] == color[r]) {
                ans = max(ans, solvedp(l, i, len[r]+k) + solvedp(i+1, r-1, 0));
            }
        }
        return dp[l][r][k] = ans;
    }
    
    int main() {
        int cases, cc = 0;
        scanf("%d", &cases);
        while (cases--) {
            int n;
            scanf("%d", &n);
            for (int i = 0; i < n; i++)
                scanf("%d", &block[i]);
            block[n] = n + 1;
            int colcnt = 0, calc = 1;
            memset(table, -1, sizeof(table));
            for (int i = 0; i < n; i++) {
                if (block[i] == block[i+1])
                    calc += 1;
                else {
                    color[colcnt] = block[i];
                    len[colcnt] = calc;
                    pre[colcnt] = table[block[i]];
                    table[block[i]] = colcnt;
                    calc = 1;
                    colcnt += 1;
                }
            }
            memset(dp, -1, sizeof(dp));
            int ans = solvedp(0, colcnt - 1, 0);
            printf("Case %d: %d\n", ++cc, ans);
        }
        return 0;
    }
    -------------------------------------------------------

    kedebug

    Department of Computer Science and Engineering,

    Shanghai Jiao Tong University

    E-mail: kedebug0@gmail.com

    GitHub: http://github.com/kedebug

    -------------------------------------------------------

  • 相关阅读:
    随机生成几位数
    文件下载
    动态SQL
    springmvc的xml版本和注解版本
    Hibernate与MyBatis
    关于过滤器!!
    jsp-EL表达式
    SpringMVC 自定义类型转换器
    Spring MVC 知识点记忆
    cmd的操作命令导出导入.dmp文件
  • 原文地址:https://www.cnblogs.com/kedebug/p/2997600.html
Copyright © 2011-2022 走看看