区间 dp 通过合并区间实现。若设计的状态空间较大考虑离散化。
状态令
fi,j 为一个区间的最优值,特定情况下加上一维。转移通常为
O(n2),如果是环,先断环为链。
P1005 矩阵取数游戏
每次取边缘值。
边缘值,意味着?余下能取的数还是一个区间。而对于每一行是独立的。
fi,j=max{fi−1,j+ai−1×2m−j+i−1,fi,j+1+aj+1×2m−j+i−1}
高精不说,注意区间 dp 不存在空区间,所以枚举长度为一的区间模拟最终删除。
CF1114D Flood Fill
有一个长度为
n 的序列,定义
[i,j] 为联通块当且仅当
[i,j] 内的元素为同一颜色。每次可以将一个联通块的颜色染成另一个颜色,求最少染多少次才能让
[1,n] 是一个联通块。
先将相同的颜色缩成一个元素。状态转移为
fi,j=fi+1,j−1+1(i=j)
fi,j=max{fi+1,j,fi,j−1}+1(i=j)
P1220 关路灯
有
n 盏灯,每盏灯都有功率,老张在第
i 盏灯前。老张每秒可以从一个灯移动到与它相邻的灯,关掉一个灯不用时间。问最少消耗的电功率。
因为关灯不用时间,所以路过的灯都顺手关掉,意味着关掉
[i,j] 的灯最后位置不在
i 就在
j。设
fi,j,0 为关掉了
[i,j] 灯,停留在
i 上最小总电功,
fi,j,1 为停留在
j 上的最小总电功。对于一个
[i,j],如果最后在
i,可能是从
i−1 走来的,也有可能是从
j 掉头回来的,求最小值即可。对于
j 同理。先前缀和预处理
sum。
fi,j,0=minfi+1,j,0+(ai+1−ai)×(sumn+sumi−sumj), fi+1,j,1+(aj−ai)×(sumn+sumi−sumj)
fi,j,1=minfi,j−1,0+(aj−ai)×(sumn+sumi−1−sumj−1), fi,j−1,1+(aj−aj−1)×(sumn+sumi−1−sumj−1)
当然,若将灯坐标的范围扩大,可以离散化。
P1880 石子合并
一些数排成一环,可以将相邻的两个数合并,权值为两数之和,求合并为一个数的最大权值和最小权值。
只考虑最大权值,先将长度为
n 的环切成长度为
n×2 的链。设
fl,r 为将
[l,r] 的数合并为一堆的最大权值,可以枚举一个分界点,用前缀和预处理。dp 完后扫一遍取最大值即可。转移方程为
fl,r=max{fl,k∈[l,r)+fk+1,r+sumr−suml−1}
POJ 2955 Brackets
给定一个括号序列,求最长合法括号子序列的长度。合法的括号序列满足下列条件
- 空的括号序列是合法的。
- 如果一个括号序列 s 是合法的,那么 (s) 和 [s] 都是合法的。
- 如果两个括号序列 a 和 b 都是合法的,那么 ab 也是合法的。
- 其他的括号序列都是不合法的。
设
fl,r 为
[l,r] 的最大匹配数。
for (int i = 1; i < n; i++)
for (int l = 0; l < n - i; l++){
int r = l + i;
if (s[l] == '(' && s[r] == ')' || s[l] == '[' && s[r] == ']')
dp[l][r] = dp[l + 1][r - 1] + 2;
for (int j = l; j < r; j++)
dp[l][r] = max(dp[l][r], dp[l][j] + dp[j + 1][r]);
}
SCOI2003 字符串折叠 & SCOI2007 压缩
求一个字符串的最短可嵌套压缩长度。如 AAAAAAAAAABABABCCD
最短为 9(A)3(AB)CCD
对于一个字符串,令
fi,j 为
[i,j] 的最短压缩长度,有三个压缩。
- 原串形式,将
fi,j 赋初值为
j−i+1。
- 拼接形式,枚举拼接点
k,
fi,j=min{fi,j,fi,k+fk+1,j}。
- 嵌套形式,枚举嵌套的周期长度,若能嵌套,则转移,与重复次数的位数
+2 即两个括号
+ 周期长度取 min。
IOI1998 Polygon
给定一个环,先删一条边,再每次选择一条边,将对应的两点合并,点权为原来两个点的点权进行边上符号的运算即为加法或乘法。求只余下一个点的最大点权。
先将长度为
n 的环切成长度为
n×2 的链。设
fi,j 为区间
[i,j] 的最大值。是不是枚举分界点
k 进行区间合并?对,那就错了,因为乘法负负得正。可能两个极小的负值相乘为正值,所以用
gi,j 表示最小值。
fi,j=max{fi,j,max{fi,j×fk+1,j,max{gi,k×gk+1,j,max{fi,k×gk+1,j,gi,k×fk+1,j}}}}
gi,j=min{gi,j,min{fi,k,fk+1,j,min{gi,k×gk+1,j,min{fi,k×gk+1,j,gi,k×fk+1,j}}}}
HAOI2008 玩具取名
有 WING
四个字母,每个字母可以用 WING
中给定的任意两个字符代替,给定一个字符串,求它可以还原成WING
中哪几个字母。
如果正向还原,比较复杂,不如看作压缩。如果按字符,比较复杂,不如将字符转换为数字。有趣的是,该题不让我们求最优方案而是问有无方案,所以设
fi,j,k 为
[i,j] 区间内的数字能否通过
k 转换来。对于转移,枚举一个分界点
mid,检验
mid 两边能不能压缩成任意可以压缩成
k 的两个字符即可。
CQOI2007 涂色
将一个空字符串涂成给定的目标颜色字符串,每次可以涂一个区间覆盖之前的颜色,求最少涂色次数。
设
fi,j 为将
[i,j] 涂成目标颜色的最少次数。初值当
i=j 时涂一次,当
i=j∨si=sj 时,在涂
[i,j−1] 或
[i+1,j] 时多涂一格即可。当
i=j∨si=sj 时,枚举分界点
k,将
[i,j] 分成
[i,k] 与
[k+1,j] 两块来涂色即可。