区间dp
区间DP
- 是一类子问题从短到长,而不是从左到右的动态规划问题。
状态
一般是: 表示将区间 的元素合并、拆分的最值、方案数。
转移
1 | for (int len = 2; len <= n; len++)//这问题 |
例题
洛谷P1775
设有 堆石子排成一排,其编号为 。每堆石子有一定的质量 。现在要将这 堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻。合并时由于选择的顺序不同,合并的总代价也不相同。试找出一种合理的方法,使总的代价最小,并输出最小代价。
状态
表示将区间 的元素合并的最小代价。
转移
1 | for (int k = i; k < j; k++) |
答案
洛谷P3146
贝西喜欢在手机上下载游戏来玩,尽管她确实觉得对于自己巨大的蹄子来说,小小的触摸屏用起来相当笨拙。
她对当前正在玩的这个游戏特别感兴趣。游戏开始时给定一个包含 个正整数的序列(),每个数的范围在 之间。在一次操作中,贝西可以选择两个相邻且相等的数,将它们替换为一个比原数大 1 的数(例如,她可以将两个相邻的 7 替换为一个 8)。游戏的目标是最大化最终序列中的最大数值。请帮助贝西获得尽可能高的分数!
状态
表示将区间 的元素合并的最大能得到的数。
转移
1 | for (int k = i; k < j; k++) |
答案
洛谷P1622
Caima 王国中有一个奇怪的监狱,这个监狱一共有 个牢房,这些牢房一字排开,第 个紧挨着第 个(最后一个除外)。现在正好牢房是满的。
上级下发了一个释放名单,要求每天释放名单上的一个人。这可把看守们吓得不轻,因为看守们知道,现在牢房中的 个人,可以相互之间传话。如果某个人离开了,那么原来和这个人能说上话的人,都会很气愤,导致他们那天会一直大吼大叫,搞得看守很头疼。如果给这些要发火的人吃上肉,他们就会安静点。
状态
表示将区间 的人放在一起需要给的肉的数量。
转移
1 | for (int k = i; k < j; k++) |
答案
洛谷P2890
P2890 [USACO07OPEN] Cheapest Palindrome G
给定一个由 个不同的小写字母构成的长 的字符串 。可以通过在 的任意位置增减字母将 改为回文串。增减字母的花费不同,求最小花费。
状态
表示将区间 变成回文串的最小花费。
转移
1 | if (s[i] == s[j]) |
答案
类似题
- P1435 [IOI 2000] 回文字串,只不过代价为 。
洛谷P2858
P2858 [USACO06FEB] Treats for the Cows G/S
约翰经常给产奶量高的奶牛发特殊津贴,于是很快奶牛们拥有了大笔不知该怎么花的钱。为此,约翰购置了 () 份美味的零食来卖给奶牛们。每天约翰售出一份零食。当然约翰希望这些零食全部售出后能得到最大的收益,这些零食有以下这些有趣的特性:
- 零食按照 编号,它们被排成一列放在一个很长的盒子里。盒子的两端都有开口,约翰每天可以从盒子的任一端取出最外面的一个。
- 与美酒与好吃的奶酪相似,这些零食储存得越久就越好吃。当然,这样约翰就可以把它们卖出更高的价钱。
- 每份零食的初始价值不一定相同。约翰进货时,第i份零食的初始价值为 ()。
- 第i份零食如果在被买进后的第 天出售,则它的售价是 。
的是从盒子顶端往下的第i份零食的初始价值。约翰告诉了你所有零食的初始价值,并希望你能帮他计算一下,在这些零食全被卖出后,他最多能得到多少钱。
状态
表示只将区间 买完的最大价值。
转移
1 | dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]) + sum[j] - sum[i - 1]; |
答案
洛谷P4170
状态
表示将区间 达到目标的最少涂色次数。
转移
1 | if (s[i] == s[j]) |
答案
洛谷P3205
…
小 A 心中有一个理想队形,他想知道多少种初始队形可以获得理想的队形。
请求出答案对 取模的值。
状态
表示这一次是添加到开头/结尾,将区间 达到理想的队形的方案数。
转移
1 | if (a[i] < a[i + 1]) |
答案
总结
- 题目特征上有合并类、拆分类、两端处理类;
- 求最值类区间DP,需要注意无效状态初始化;
- 输出答案前,判断是否需要枚举;
- 决策点一般是在中间枚举或是两个端点;
- 若转移时可以从 递推,需要注意 的情况;
- 初始状态要分析清楚。