http://poj.org/problem?id=3280
观察题目我们可以知道,实际上对于一个字母,你在串中删除或者添加本质上一样的,因为既然你添加是为了让其对称,说明有一个孤立的字母没有配对的,也就可以删掉,也能满足对称。 故两种操作看成一种,只需要保留花费少的那个即可
然后 令 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 <cstdio> #include <cmath> #include <vector> #include <cstring> #include <string> #include <algorithm> #include <string> #include <set> #include <functional> #include <numeric> #include <sstream> #include <stack> #include <map> #include <queue> #pragma comment(linker, "/STACK:102400000,102400000") #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long #define inf 0x7f7f7f7f #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define L(x) (x) << 1 #define R(x) (x) << 1 | 1 #define MID(l, r) (l + r) >> 1 #define Min(x, y) (x) < (y) ? (x) : (y) #define Max(x, y) (x) < (y) ? (y) : (x) #define E(x) (1 << (x)) #define iabs(x) (x) < 0 ? -(x) : (x) #define OUT(x) printf("%I64d ", x) #define lowbit(x) (x)&(-x) #define Read() freopen("a.txt", "r", stdin) #define Write() freopen("b.txt", "w", stdout); #define maxn 1000000000 #define N 2020 #define mod 1000000000 using namespace std; int dp[N][N]; int cost[30]; char s[N]; int main() { //Read(); int n,m,a,b; char str[2]; while(~scanf("%d%d",&n,&m)) { getchar(); scanf("%s",s); for(int i=0;i<n;i++) { scanf("%s%d%d",str,&a,&b); cost[str[0]-'a']=min(a,b); } memset(dp,0,sizeof(dp)); for(int i=m-1;i>=0;i--) { for(int j=i+1;j<m;j++) { if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]; else dp[i][j]=min(dp[i+1][j]+cost[s[i]-'a'],dp[i][j-1]+cost[s[j]-'a']); //printf("%d ",dp[i][j]); } } printf("%d ",dp[0][m-1]); } return 0; }