DP-最小的回文代价
描述
小明今天刚学完“字符串类型”这一节内容,学到了一个新的概念,回文字符串,大家都知道回文串的概念,一个字符串正向读和反向读是相同的,例如aba,abcba等等(空串也视为回文串),现在我们的任务是将一个字符串S变成回文串。我们可以通过删除某个字符或者添加某个字符的组合操作使它成为回文串,但是每个操作都有一个代价,现在我们希望花费最小的代价使这个字符串变为回文串。字符串都由小写字母组成。
输入描述
第一行为正整数t(≤10),表示数据组数;
...
对于每组数据,输出使S串变成回文串花费的最小代价。
思路
-
dp[i][j]表示i到j的回文代价
-
一个区间dp
-
如果s[i]=s[i+l] (i为起点,l为长度),dp[i][i+l]=dp[i+1][i+l-1] (起点+1,终点-1.也就是各向里缩一个)
-
否则,dp[i][i+l]=min({右增加,右减少,左增加,左减少});
-
有多组样例,一定要重新初始化!!!
-
不开long long见祖宗
代码
#include<bits/stdc++.h>
using namespace std;
int n, tot, ans, c[5005], s[5005], k;
long long f[5005][5005];
char a[5005], ch;
int main() {
int t;
cin >> t;
while (t--) {
cin >> k >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
for (int i = 1; i <= k; ++i) {
cin >> ch;
cin >> c[ch - 'a'];
cin >> s[ch - 'a'];
}
for (int l = 1; l < n; ++l) {
for (int i = 1; i + l <= n; ++i) {
if (a[i] == a[i + l])
f[i][i + l] = f[i + 1][i + l - 1];
else {
int s1 = f[i][i + l - 1] + c[a[i + l] - 'a'], s2 = f[i][i + l - 1] + s[a[i + l] - 'a'], s3 = f[i + 1][i + l] + c[a[i] - 'a'], s4 = f[i + 1][i + l] + s[a[i] - 'a'];
f[i][i + l] = min(min(s1, s2), min(s3, s4));
}
}
}
printf("%lld\n", f[1][n]);
}
return 0;
}