题目大意:在原字符串中添加或删除字母,使其成为回文串,添加、删除每个字母的代价不同,问最小代价是多少
输入:原字符串包含的字母种类数N 原字符串长度M(1<=N<=26)(1<=M<=2000)
原字符串
第i种字母 添加代价 删除代价(0<=cost<=10000)
输出:最小代价
分析:区间动态规划
状态dp[i][j]:i到j变为回文串的最小代价
结果:dp[0][m-1]
初始化:dp[i][i]=0
状态转移方程:if(s[i]=s[j]) dp[i][j]=dp[i+1][j-1] //前后匹配
else dp[i][j]=min{ dp[i+1][j]+min{add[i],del[i]}, //不匹配,添加或删除s[i]使成为回文串
dp[i][j-1]+min{add[j],del[j]} } //不匹配,添加或删除s[j]使成为回文串
代码:转载自http://blog.csdn.net/y990041769/article/details/24259569(有稍加改动)
#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 200;
const int M = 2500;
int add[N];
int dp[M][M];
int main()
{
int n,m;
string s;
while(~scanf("%d%d",&n,&m))
{
cin>>s;
char c;int x,y;
for(int i=0;i<n;i++)
{
cin>>c>>x>>y;
add[c]=min(x,y);
}
memset(dp,0,sizeof(dp));
for(int k=1;k<s.size();k++)
{
for(int i=0,j=k;j<s.size();i++,j++)
{
dp[i][j]=0x3f3f3f3f;
if(s[i]==s[j])
dp[i][j]=dp[i+1][j-1];
else
{
dp[i][j]=min(dp[i+1][j] + add[s[i]],dp[i][j]);
dp[i][j]=min(dp[i][j-1] + add[s[j]],dp[i][j]);
}
}
}
printf("%d\n",dp[0][s.size()-1]);
}
return 0;
}