区间dp

P1880 [NOI1995] 石子合并(破环成链+石子合并类套路)

题目

在一个圆形操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆,规定每次只能选相邻的 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出一个算法,计算出将 N 堆石子合并成 1 堆的最小得分和最大得分。

1N1000ai20

题解

环形的序列,那么断开环,倍长序列去做

f[l][r] 表示合并区间 [l,r] 中的所有石子所能带来的最大收益,sum[l][r] 表示 [l,r] 中石子个数的和,转移方程如下

f[l][r]=maxlkr{f[l][k]+f[k+1][r]+sum[l][r]}

时间复杂度为 O(n3),可以使用四边形不等式优化到 O(n2) ,但这不是提高组的考察范围

HDU 4283 You Are the One (栈的性质+石子合并类套路)

题目

有一个长为 N (N100) 的队列,第 i 个人有一个愤怒值 Di,如果他是第 K 个上场,不开心指数就为 (K1)D。但是边上有一个小黑屋(后进先出,当成个堆栈),可以一定程度上调整上场顺序,使不开心指数最小

题解

考虑栈的性质,第 i 个元素入栈,如果它最终的位置是在 k,那么 ik 这一段中不可能有 k 位置后的数出现。因此把问题 [l,r] 分为子问题 [l+1,k],[k+1,r],直接转移即可

时间复杂度 O(N3)

P1005 [NOIP2007 提高组] 矩阵取数游戏 (取两端套路)

题目

题解

首先一轮一轮的考虑是困难的,所以我们一行一行的考虑

这样原问题可以转化对每一行确定选数的顺序

那么就可以通过区间dp转移了,假设要选完 [l,r] 中的数,由于每次只能取两边的数,那么就从 [l,r1]×2 或者 [l+1,r]×2 转移而来

时间复杂度 O(mn2)

P3205 [HNOI2010]合唱队 (取两端套路+增加维数)

题目

题解

考虑对理想队形进行区间dp,假设此时考虑排成区间 [i,j] 队形的方案数,但是如果采取普通的 f[i][j] 的二维dp考虑,我们发现我们无法转移

原因是我们dp的状态中缺少上一次的值放在了那里这一个信息,所以将状态修改为 f[i][j][0/1] 表示排成区间 [i,j] 中的队形且第 i 个人在左端/第 j 个人在右端时的方案数

转移如下

if(a[i]<a[i+1])f[i][j][0]+=f[i+1][j][0];
if(a[i]<a[j])f[i][j][0]+=f[i+1][j][1];
if(a[j]>a[i])f[i][j][1]+=f[i][j-1][0];
if(a[j]>a[j-1])f[i][j][1]+=f[i][j-1][1];

初始状态注意把所有的数都当成从左边进来的,不然会算重,时间复杂度 O(n2)

P1220 关路灯 (提前计算贡献)

题目

题解

首先考虑如果经过一个灯而不关掉它显然是不优的,所以每次关掉的灯一定是一段连续的区间

于是设 f[i][j][0/1] 表示关掉了区间 [i,j] 中所有的灯之后,身处最左端/右端时的所有的灯总的功耗和

那么就有转移

f[l][r][0]=min(f[l+1][r][0]+(p[l+1]-p[l])*(pre[l]+pre[n]-pre[r]),f[l+1][r][1]+(p[r]-p[l])*(pre[l]+pre[n]-pre[r]));
f[l][r][1]=min(f[l][r-1][1]+(p[r]-p[r-1])*(pre[l-1]+pre[n]-pre[r-1]),f[l][r-1][0]+(p[r]-p[l])*(pre[l-1]+pre[n]-pre[r-1]));

其实这本质是个贪心, dfs 也是可以做的

时间复杂度 O(n2)

P4170 [CQOI2007]涂色 (涂色类套路)

题目

给定一个长度为 n (n500) 的木板,初始没有颜色。

我们现在要在上面涂色,每次涂色必须涂连续的一段区间且可以覆盖之前涂过的颜色

问使初始木板变成目标颜色的最小操作次数

题解

f[i][j] 表示将区间 [i,j] 中的位置变成目标颜色的方案数

那么考虑分类讨论

  • i=j,则有 f[i][j]=1

  • col[i]=textcol[j] ,那么我们直接在端点处染色即可

  • col[i]col[j] ,那么我们就枚举一个分界点,左右两边涂不同的颜色

状态转移如下

if(l==r) f[l][r]=1
else if(s[l]==s[r]) f[l][r]=min(f[l+1][r],f[l][r-1]);
else if(s[l]!=s[r]) for(int k=l;k<r;k++) f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);

时间复杂度 O(n3)

HDU 2476 String painter (分步涂色)

题目

给定两个初始串 a,b ,求将 a 区间染色成 b 的最小步数

|a|=|b|500

题解

首先一个朴素的思路是直接设 f[i][j] 表示将 a 中的 [l,r] 染成 b 的最小步数

但是你要分十万种情况讨论,理论可行,但不可做

所以我们考虑这样一个过程,我们可以先计算从无色串到 b 的最小步数,这就是“Luogu P4170 [CQOI2007]涂色”,然后我们对 a 进行一个dp求出它那些位置需要染色,假设我们求出无色串染色区间 [l,r] 染成 b 的最小次数为 f[l][r]

考虑如何对 a 序列进行dp,设 g[i] 表示考虑将 a 的前 i 位染色至 b 的最小的方案数,考虑如何进行转移,假设当前考虑到第 i

  • 如果 a[i]=b[i] ,那么 g[i]=g[i1] 无需染色
  • 如果 a[i]b[i] ,那么我们枚举染色的分界点 j,转移方程为

g[i]=min1ji1g[j]+f[j+1][i]

时间复杂度 O(n3)

P7914 [CSP-S 2021] 括号序列(通过增维实现对不同情况的分类讨论)

题目

题解

首先,朴素的思路是设 f[i][j] 表示区间 [l,r] 中合法的超级括号序列的数量,但是我们注意到题目中有“连续的 不超过 k 个”这一个条件,所以我们记录的这个状态记录的信息不够,所以考虑增维

f[i][j][p],p[0,5] , A 表示左右两边都是括号且这两个括号不匹配的串,其中

  • p=0 表示全是 的情况
  • p=1 表示 (A) 的情况
  • p=2 表示 AS 的情况
  • p=3 表示 A 的情况,注意该状态包含 p=1 的状态
  • p=4 表示 SA 的情况
  • p=5 表示 SAS 的情况,注意该状态包含 p=0 的状态

下面我们来考虑转移,思路就是在已有的 2,3,4,5 后边接上 0,1 这两个基本单位来转移

  • p=0 时,对 len 进行一个特判即可
  • p=1 时,如果当前区间 [l,r] 的左右端点不匹配则为 0 ,否则注意一下转移时不能有 (SAS) 的情况,于是转移为

f[l][r][1]=f[l+1][r1][0]+f[l+1][r1][2]+f[l+1][r1][3]+f[l+1][r1][4];

  • p=2 时,我们就是要拿 A 拼上 S ,这里不拿 ASS 是为了满足长度不超过 k 的方案数,于是转移如下

f[l][r][2]=i=lr1f[l][i][3]×f[i+1][r][0]

  • p=3 时,我们可以通过 AS 拼上 (A) 或者 A 拼上 (A) ,注意加上 p=1 的情况

f[l][r][3]=i=1r1(f[l][i][2]+f[l][i][3])×f[i+1][r][1]+f[l][r][1]

  • p=4 时,我们就是要找开头为 的即 SA,SAS 的后面拼接 (A)

f[l][r][4]=i=1r1(f[l][i][4]+f[l][i][5])×f[i+1][r][1]

  • p=5 时,我们就是要找开头为 的即 SA 的后面拼接 S ,另外别忘了还有 S

f[l][r][5]=i=1r1f[l][i][4]×f[i+1][r][0]+f[l][r][0]

答案必须为首尾都是括号序列.所以就为 f[1][n][3]

这样dp的时间复杂度为 O(n3)

posted on   star_road_xyz  阅读(18)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示