解题思路:区间DP,注意对于回文串,删除与增加一个字母效果是一样的,所以,只需要存储增删两者的最小值即可,然后区间DP,我之前想太复杂了,用的是非动态规划思维去思考的,所以刚开始感觉好难。
首先,用递归的思维去推状态转移方程,比如i到j区间的最优解是由i+1-j,i-j-1,i+1-j-1这三个子问题转移过来的,详细解释看code
这里写代码片
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2000 + 10;
int dp[maxn][maxn];
int cost[maxn];
int n = 0,m = 0;
string str1;
char str2;
int main(){
int a = 0,d = 0;
cin >> n >> m;
cin >> str1;
memset(dp,0,sizeof(dp));
for(int i = 1;i <= n;++i){
cin >> str2 >> a >> d;
cost[str2 - 'a'] = min(a,d);
}
/*
//首先是状态建立,dp[i][j]表示的是从j到i区间的最小转化代价
for(int i = 1;i < m;++i){
for(int j = i - 1;j >= 0;--j){
dp[i][j] = min( dp[i-1][j] + cost[str1[i] - 'a'] , dp[i][j+1] + cost[str1[j]-'a']);
if(str1[i] == str1[j]){
dp[i][j] = min( dp[i][j] , dp[i-1][j+1]);
}
}
}
*/
//dp[i][j]表示的是从i到j区间的最小转化代价
for(int len = 2;len <= m;++len){
for(int i = 0;i < m-len + 1;++i){
int j = i + len - 1;
dp[i][j] = min( dp[i+1][j] + cost[str1[i] - 'a'] , dp[i][j-1] + cost[str1[j]-'a']);
if(str1[i] == str1[j]){
dp[i][j] = min( dp[i][j] , dp[i+1][j-1]);
}
}
}
cout << dp[0][m-1] << endl;
//cout << dp[m-1][0] << endl;
return 0;
}