2.区间dp
* 区间 dp 也是线性 dp 的⼀种,它⽤区间的左右端点来描述状态,通过⼩区间的解来推导出⼤区间的解。因此,区间 DP 的核⼼思想是将⼤区间划分为⼩区间,它的状态转移⽅程通常依赖于区间的划分点。
常⽤的划分点的⽅式有两个:
• 基于区间的左右端点,分情况讨论;
• 基于区间上某⼀点,划分成左右区间讨论。
1.回文字串
回⽂词是⼀种对称的字符串。任意给定⼀个字符串,通过插⼊若⼲字符,都可以变成回⽂词。此题的任务是,求出将给定字符串变成回⽂词所需要插⼊的最少字符数。⽐如Ab3bd插⼊2个字符后可以变成回⽂词dAb3bAd或Adb3bdA,但是插⼊少于2个的字符⽆法变成回⽂词。
可以发现如下性质:
• 对角线以下是⽤不到的⾮法区域,因为这个区域中的左端点⼤于右端点,不符合区间的定义;
• 每⼀个格⼦填表的时候,需要左边的格⼦以及下边的格⼦;
• 当 的时候,填格⼦会⽤到⾮法区域,并且 以及 的时候会越界,需要特殊处理。综上所述:
• 对于初始化:
我们需要初始化对⻆线位置的值。因为对⻆线表⽰⻓度为1的字符串,本⾝就是回
⽂串,⾥⾯的值是0即可。• 对于填表顺序,我们有两种策略:
1.从下往上填写每⼀⾏,每⼀⾏从左往右。
这样就能保证在填写[i,j]位置时,[i+1,j]及[i,j-1]已经被更新过了。
2.第⼀维循环:⼩到⼤枚举区间⻓度len(2<=len<=n);第⼆维循环:枚举区间左端点i;
然后计算出区间右端点j=i+len-1。这样我们填表的时候,就是⼀个对⻆线⼀个对⻆线的
填,不会产⽣越界访问的问题。对于区间dp的填表顺序,我们⼀般选取第⼆种,会让我们的代码看着很清晰,也⽐较符合区间dp
的推导过程,从⼩区间递推到⼤区间。
2.石子合并(弱化版)
设有N(N<=300)堆⽯⼦排成⼀排,其编号为1,2,3,...N 。每堆⽯⼦有⼀定的质量 m i ( mi ≤ 1000) 现在要将这N堆⽯⼦合并成为⼀堆。每次只能合并相邻的两堆,合并的代价为 这两堆⽯⼦的质量之和,合并后与这两堆⽯⼦相邻的⽯⼦将和新堆相邻。合并时由于选择的顺序不 同,合并的总代价也不相同。试找出⼀种合理的⽅法,使总的代价最⼩,并输出最⼩代价。

3.石子合并
在⼀个圆形操场的四周摆放N堆⽯⼦,现要将⽯⼦有次序地合并成⼀堆,规定每次只能选相邻的2
堆合并成新的⼀堆,并将新的⼀堆的⽯⼦数,记为该次合并的得分。试设计出⼀个算法,计算出将 N 堆⽯⼦合并成 1 堆的最⼩得分和最⼤得分
处理环形问题的技巧:倍增。
在数组后⾯,将原始数组复写⼀遍,然后在倍增之后的数组上做⼀次⽯⼦合并(弱化版),就能得到
以所有位置为起点并且⻓度为 len 的最⼩合并代价。