实际上对于一个字母,你在串中删除或者添加本质上一样的,因为既然你添加是为了让其对称,说明有一个孤立的字母没有配对的,也就可以删掉,也能满足对称。
故两种操作看成一种,只需要保留花费少的那个即可
然后
令
dp[i][j]表示从位置i到j的子串转化为回文串需要的次数
若 s[i]== s[j] 则dp[i][j] = dp[i + 1][j - 1]
否则 dp[i][j] = min(dp[i+1][j] + cost[i], dp[i][j - 1] + cost[j])
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAX 2111
using namespace std;
int dp[MAX][MAX];
int cost[300];
char ch[MAX];
int N,M;
int DP()
{
int i,j,k,r;
for(i=0;i<M;i++) dp[i][i]=0;
for(r=2;r<=M;r++) //子段的长度
for(i=0;i<=M-r;i++) //i为首指针,j为尾指针。
{
j=i+r-1;
if(ch[i]==ch[j])
dp[i][j]=dp[i+1][j-1];
else
{
dp[i][j]=min(dp[i+1][j]+cost[ch[i]],dp[i][j-1]+cost[ch[j]]);
}
}
return dp[0][M-1]; //最优解
}
int main()
{
int i,j;
char c;
int ins,del;
scanf("%d%d",&N,&M);
getchar();
gets(ch);
for(i=0;i<N;i++)
{
scanf("%c%d%d",&c,&ins,&del);
getchar();
cost[c]=min(ins,del);
}
int ans=DP();
printf("%d\n",ans);
return 0;
}