DP提高专项1题解

主要讲一下每一题的做法以及思考方式。

感觉难度薇 T1T3T2 。但是都不算难。

T1

题目描述

Jimmy 最近迷上了一款叫做方块消除的游戏。游戏规则如下:n 个带颜色方格排成一列,相同颜色的方块连成一个区域(如果两个相邻方块颜色相同,则这两个方块属于同一区域)。为简化题目,将连起来的同一颜色方块的数目用一个数表示。

例如,9 122233331 表示为

4
1 2 3 1
1 3 4 1

游戏时,你可以任选一个区域消去。设这个区域包含的方块数为 x,则将得到 x2 个分值。方块消去之后,其余的方块就会竖直落到底部或其他方块上。而且当有一列方块被完全消去时,其右边的所有方块就会向左移一格。Jimmy 希望你能找出得最高分的最佳方案,你能帮助他吗?

第一行包含一个整数 m1m50),表示同颜色方块区域的数目。
第二行包含 m 个数,表示每个区域的颜色(1m 之间的整数)。
第三行包含 m 个数,表示每个区域包含的方块数(120 之间的整数)。

思路点拨

挺简单的一题。考虑到本题从序列中间开始操作会得到不同的结果,所以不可以使用类似于子序列提取的线性dp,而是考虑区间dp。

我们比较头疼的是,在消除完之后右边的方块会挪过来,所以我们可以在状态中体现这一点。我们定义 fl,r,k 表示是目前考虑了区间 l,r 的方格,右端点右边接了 k 个与之颜色相同过的方块的最大价值。

转移分两类讨论:

  • 把右边炸了!

fl,r,k=fl,r1,0+(num[r]+k)2

  • 考虑炸掉中间一段,然后右边的 (num[r]+k) 移到左边去(要求左边与右边颜色相同)

fl,r,k=fl,mid,num[r]+k+fmid+1,r1,0

别的不需要多多考虑,因为我们最为简单的方式就是从左到右依次炸掉,我们不论怎么操作,答案不会劣于这个。所以我们只需要考虑让颜色相同的尽量在一起炸掉。

时间复杂度 O(n4)

代码很短,不放了。

T3

题目描述

现在有 n 个元素,构成一颗二叉排序树。还知道这颗二叉排序树父子之间权值不互质,问是否存在这样的树?

n700

思路点拨

二叉排序树的性质:中序遍历是有序的。我们考虑对原序列排序之后区间 dp ,按照中序遍历 dp

因为需要父子之间权值互质,所以我们在状态里记录一下根。设 fl,r,k 表示考虑到区间 l,r ,根位 k 是否可以满足条件。那么

fi,j,k=(ir<kfi,k1,r[gcd(ak,ar)>1])(k<rjfk+1,j,r[gcd(ak,ar)>1])

时间复杂度 O(n4) ,不可以通过。

考虑优化,我们发现我们做了一个十分智障的操作。我们在状态里面记录根的目的就是为了保证根与根的父亲不互质,但是没有必要将根表示出来。因为对于区间 [l,r] 而言,它的根的父亲无非就是 l1,r+1 两种。所以我们可以更改一下状态:

fl,r 表示考虑到区间 [l,r] ,根的父亲是 l1 的方案。

gl,r 表示考虑到区间 [l,r] ,根的父亲是 r+1 的方案。

转移方式几乎不变,枚举一个根(vis 数组表示是否互质):

	for(int len=2;len<=n;len++)
		for(int l=1,r=len;r<=n;l++,r++)
			for(int mid=l;mid<=r;mid++){
				if(vis[mid][r+1]) f[l][r]|=(f[l][mid-1]&g[mid+1][r]);
				if(vis[mid][l-1]) g[l][r]|=(f[l][mid-1]&g[mid+1][r]);
			}

时间复杂度 O(n3)

T2

题目描述

Dreamoon 有一个字符串 s 和一个模式串 p,他会先从 s 中删除恰好 x 个字符来产生一个新的字符串 s。然后他会计算 occ(s,p),即从 s 中能找到的等于 p 的不相交的子串数量的最大值。他想让 occ(s,p) 的值尽可能大。

更形式地说,让我们用 ans(x) 表示所有可以从 s 中删去恰好 x 个字符得到的 socc(s,p) 的最大值。Dreamoon 想要知道对于所有的 x (0x|s|)ans(x) 的值。

|s|2000,|p|500

思路点拨

本场比赛最有思维含量的一题,比较靠设状态。

看到题目,这题挺 KMP 的。我们定义状态 fi,j,k 表示目前考虑到下标 i ,删除了 j 个字符,目前 KMP 的失配指针在 p 字符串的下标 k 时,以及匹配的 p 的数量的最大值。

转移可以刷表。对于 fi,j,k 而言,我们考虑 i+1 的状态:

  • 删了

  • 不删,此时维护 KMP 的失配指针。

特别好想,时间 O(|s|2|p|) ,不可以通过。

发现,上面这个 dp 因为依赖了 KMP 这个类似于自动机的东西,所以我们的第三维无法优化掉,所以我们换思考方向,将 p 作为一个整体去思考。

那么我们又可以得出如下状态:

fl,r 表示区间 l,r 是否可以提取出子序列 p ?如果可以,那么 fl,r=rl+1|p| ,如果不可以 fl,r=inf 。这是很好预处理,不讲。

dpi,j 表示考虑到下标 i ,删除了 j 个字符的情况下,匹配 p 的最大值。转移比较明了:

dpi,j=max{dpmid,jfmid+1,i+1}

时间复杂度 O(|s|3) 。虽然比较劣,但是我们发现状态有优化的空间。

我们假设,gi 表示从下标 i 往左边找,能够平凑处 |p| 这个子序列的最大下标。从 gi 开始,我们的 f 数组 +1gi 之前的东东我们可删可不删,而只有在 [gi,i] 之间的元素我们必须删除,我们可以简单改一下状态。

dpi,j 表示考虑到下标 i至少 删除了 j 个字符的情况下,匹配 p 的最大值。转移比较明了:

dpi,j=max{dpgi1,jfgi,i+1,dpi1,j,dpi1,j1}

大概就是这样,优势在于决策点减少了。具体细节不讲。

时间复杂度 O(|s|(|s|+|p|))

posted @   Diavolo-Kuang  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示