Blocks题解(区间dp)

Blocks题解

区间dp

阅读体验。。。https://zybuluo.com/Junlier/note/1289712
很好的一道区间dp的题目(别问我怎么想到的)

dp状态

其实这个题最难的地方是这道题目的状态怎么设

  • 首先既然是区间dp,那肯定最先想到的状态是

    $dp[i][j]$表示消掉区间$[i,j]$上所有的块的最大分数

  • 突然发现这个状态会受区间外和$i$或$j$颜色相同的块的影响
    并且转移也并不好转移=_=
  • 所以我们考虑换一种状态。。。
    既然说会受到外面的块的影响?那考虑一种方法来解决

    $dp[i][j][k]$表示消掉区间$[i,j]$并且区间$[i,j]$右边还有k个和j颜色相同的块(除此之外,这个序列没有别的块了),消掉这些所有的块的最大分数

    有点抽象,再来感性理解一下:

    当前处理的子问题$dp[i][j][k]$主体由区间$[i,j]$组成,然后与$j$相同有$k$块接在后面,这$k$块之间的其他块已经全部消完了

  • 如果实在还不明白,先看转移吧。。。
    然后可以根据我们前面的错误状态自己思考为什么加上这一维

转移

$dp[i][j][k]$:显然有两种转移
我这里是用记忆化搜索实现的

  1. 消掉j和后面的k块
    dp[i][j][k]=max(dp[i][j][k],Dfs(i,j-1,0)+(k+1)*(k+1));
  1. 对于区间$[i,j]$,中间可能有和$j$颜色相同的块,假设位置为$p$,我们可以选择消掉区间$[p+1,j-1]$中所有的块使颜色拼起来,当然这是个子问题,所以前面讲了用记忆化搜索实现
    PS: 下面代码的$nxt[p]$是预处理的在$p$前面第一个和$p$颜色相同的块的位置
    for(int p=nxt[j];p>=i;p=nxt[p])//枚举p dp[i][j][k]=max(dp[i][j][k],Dfs(i,p,k+1)+Dfs(p+1,j-1,0));

汇总

讲完这些整个程序的实现就不难了
那我直接放上代码,不好意思,没有注释

#include<bits/stdc++.h>
#define lst long long
#define ldb double
#define N 250
using namespace std;
const int Inf=1e9;
int read()
{
    int s=0,m=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')m=1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
    return m?-s:s;
}

int n;
int col[N],nxt[N],hd[N];
lst dp[N][N][N];//消掉[i,j]区间和[i,j]右边和j颜色一样的连续k个方块的最大分数

lst Dfs(int i,int j,int k)
{
    if(i>j)return 0;
    if(dp[i][j][k])return dp[i][j][k];
    dp[i][j][k]=max(dp[i][j][k],Dfs(i,j-1,0)+(k+1)*(k+1));
    for(int p=nxt[j];p>=i;p=nxt[p])
        dp[i][j][k]=max(dp[i][j][k],Dfs(i,p,k+1)+Dfs(p+1,j-1,0));
    return dp[i][j][k];
}

int main()
{
    int T=read();
    for(int tt=1;tt<=T;++tt)
    {
        n=read();
        memset(hd,0,sizeof(hd));
        memset(dp,0,sizeof(dp));
        memset(nxt,0,sizeof(nxt));
        for(int i=1;i<=n;++i)
        {
            col[i]=read();
            nxt[i]=hd[col[i]];
            hd[col[i]]=i;
        }
        printf("Case %d: %lld\n",tt,Dfs(1,n,0));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/cjoierljl/p/9685927.html

时间: 2024-10-25 22:11:44

Blocks题解(区间dp)的相关文章

【Uva10559】Blocks(区间DP)

Description 题意:有一排数量为N的方块,每次可以把连续的相同颜色的区间消除,得到分数为区间长度的平方,然后左右两边连在一起,问最大分数为多少. \(1\leq N\leq200\) Solution 区间DP,对于一个连续的同色区间,可以直接消掉,或者从左边或者右边搞到和它同色的区间和在一起再一起消掉. 读入序列时预处理一下,将各个连续同色区间处理为一个点,记录它的颜色和长度,便于处理 然后就是区间DP啦,虽然要表示左边和右边,但是左边状态也可以表示为左边序列的右边,就只要开3维就行

luogu4302字符串折叠题解--区间DP

题目链接 https://www.luogu.org/problemnew/show/P4302 分析 很明显一道区间DP题,对于区间\([l,r]\)的字符串,如果它的字串是最优折叠的,那么它的最优结果要么是所有分割出的字串最优结果之和,要么是在断点处恰好有这个区间的周期串可以进行折叠,折叠后产生的结果 状态转移 for(ri len=2;len<=n;len++){//枚举长度,套路 for(l=1;l<=n-len+1;l++){ r=l+len-1; for(ri k=l;k<r

POJ2955 Brackets 题解 区间DP

题目链接:http://poj.org/problem?id=2955[题目描述]<规则的括号序列>我们定义一个字符串序列为“规则的括号序列”当且仅当它满足如下条件:1.空字符串是规则的括号序列:2.如果字符串 s 是一个规则的括号序列,那么 (s) 和 [s] 也是规则的括号序列:3.如果字符串 a 和 b 都是规则的括号序列,那么 ab 也是规则的括号序列:4.除此之外的字符串都不能称为规则的括号序列.举个例子,下面的这些字符串都是规则的括号序列: (), [], (()), ()[],

POJ 1651 Multiplication Puzzle 题解 区间DP

题目链接:http://poj.org/problem?id=1651[题目描述]<乘法谜题>乘法谜题源自这样一个背景,我们有一行 n 张牌,平铺在桌面上,每张牌的牌面上都标有一个正整数.玩家的初始得分是 0,他接下来要进行 n-2 次操作,每次操作他都需要从桌面上取出一张牌,然后他的得分会加上他取出的这张牌与取出的这张牌的左边的牌以及取出的这张牌的右边的牌的乘积.在第 n-2 次操作结束后,桌面上将会只剩下两张牌.你的目的是帮助玩家决定取牌的顺序,使得玩家的最终得分最小.举个例子,如果一开始

HDU4632 Palindrome subsequence 题解 区间DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4632[题目描述]<回文子串数量>给你一个长度为N(N≤1000)的字符串,你输出它所有的回文子串的数量(对10007取模).只要从字符串 s 中顺序地取出一些字符(不要求连续,可以是 s 本身,不能是空串),不改变他们的顺序的情况下,这个子串是一个回文串,那么他就是一个 s 的回文子串.[输入格式]首先是一个数T(T≤50),表示测试用例的数量.接下来T行,每行包含一个字符串.[输出格式]对于每一

「kuangbin带你飞」专题二十二 区间DP

layout: post title: 「kuangbin带你飞」专题二十二 区间DP author: "luowentaoaa" catalog: true tags: - kuangbin - 区间DP - 动态规划 传送门 B.LightOJ - 1422 Halloween Costumes 题意 按顺序参加舞会,参加一个舞会要穿一种衣服,可以在参加完一个舞会后套上另一个衣服再去参加舞会,也可以在参加一个舞会的时候把外面的衣服脱了,脱到合适的衣服,但是脱掉的衣服不能再穿,参加完

【POJ-1390】Blocks 区间DP

Blocks Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 5252   Accepted: 2165 Description Some of you may have played a game called 'Blocks'. There are n blocks in a row, each box has a color. Here is an example: Gold, Silver, Silver, Sil

【日常学习】【区间DP+高精】codevs1166 矩阵取数游戏题解

题目来自NOIP2007TG3 如果在考场上我现在已经歇菜了吧 今天一整天的时间全部投在这道题上,收获不小. 先上题目 题目描述 Description [问题描述] 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m 的矩阵,矩阵中的每个元素aij均 为非负整数.游戏规则如下: 1. 每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. 每次取走的各个元素只能是该元素所在行的行首或行尾: 3. 每次取数都有一个得分值,为每行取数的得分之和,每行取数的得分= 被取走的元素

【基础练习】【区间DP】codevs1090 加分二叉树题解

2003 NOIP TG 题目描写叙述 Description 设一个n个节点的二叉树tree的中序遍历为(l,2,3,-,n),当中数字1,2,3,-,n为节点编号.每一个节点都有一个分数(均为正整数),记第j个节点的分数为di,tree及它的每一个子树都有一个加分,任一棵子树subtree(也包括tree本身)的加分计算方法例如以下: subtree的左子树的加分× subtree的右子树的加分+subtree的根的分数 若某个子树为主,规定其加分为1,叶子的加分就是叶节点本身的分数. 不考