PIPIOJ 1096 题解:魔术师PIPI(最小代价回文串,区间DP)
题目链接:http://pipioj.online/problem.php?id=1096
1. 题意
给定一个长度为 M 的字符串 S。
对每个字母 c,给出:
- 插入一个
c的代价add[c] - 删除一个
c的代价del[c]
要求把 S 变成回文串,求最小总代价。
可在任意位置进行插入/删除,且有多组数据。
2. 关键观察
对某个字符 c 来说,最终只关心“让它多一个或者少一个”的代价,因此可以先做:
cost[c] = min(add[c], del[c])
后续转移只用 cost 即可。
3. 区间 DP 设计
设 dp[i][j] 表示把子串 S[i..j] 变成回文串的最小代价(1 <= i <= j <= M)。
转移:
- 删/补左端字符:
dp[i+1][j] + cost[S[i]] - 删/补右端字符:
dp[i][j-1] + cost[S[j]] - 若
S[i] == S[j],两端可直接匹配:dp[i+1][j-1]
所以:
1 | dp[i][j] = min( |
初始化:单个字符本身是回文,dp[i][i] = 0。
遍历顺序:i 从大到小,j 从小到大,保证子问题先算好。
复杂度:
- 时间:
O(M^2)(M<=2000可过) - 空间:
O(M^2)
4. AC 代码(提交通过)
下面给出提交通过的代码(原样保留):
1 |
|
5. 一个小细节
当前代码把字符映射成 1..26,因此 cost 数组更稳妥写成 int cost[27](或直接用 cost[128] 按 ASCII 存)。
思路和转移本身是完全正确的。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 David's Blog!
评论