题意:给你一个m位的字符串,其中的字符是给定的n个小写字母之一,然后再字符串中添加或删除这字母的代价
不一样。求在添加删除操作之后的字符串成为回文串的最小代价。
思路:考虑d[i][j]为字符串i到j成为回文串的最小代价。
如Xx.....yY,如果X == Y,显然d[i][j] = d[i+1][j-1];
如果X != Y,那么有4种方案:删除X,在Y后面添加一个X,删除Y,在X前面添加Y。从而转移方程可以写成
d[i][j] = min(d[i+1][j]+del[s[i]-‘a‘], d[i+1][j]+add[s[i]-‘a‘], d[i][j-1] + del[s[j]-‘a‘], d[i][j-1] + add[s[j]-‘a‘]);
由上面的方程可以分析得,对于删除添加字符s[i],我们只用取得其中最小的代价的操作就可以了,从而方程就更短了
如d[i][j] = min(d[i+1][j]+cost[s[i]-‘a‘], d[i][j-1] + cost[s[j]-‘a‘]);
AC代码:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int M = 2005; int n,m,ch[2],cost[27],d[M][M]; char s[M]; void solve() { memset(d, 0, sizeof(d)); for(int dis = 1; dis < m; dis++) { for(int i = 0, j = i+dis; j < m; i++,j++) { if(s[i] == s[j]) d[i][j] = d[i+1][j-1]; else{ d[i][j] = min(d[i+1][j] + cost[s[i]-‘a‘], d[i][j-1] + cost[s[j]-‘a‘]); } } } printf("%d\n", d[0][m-1]); } int main() { while(~scanf("%d %d", &n, &m)) { memset(cost, 0, sizeof(cost)); scanf("%s", s); for(int i = 0; i < n; i++) { int t1,t2; scanf("%s %d %d", ch,&t1, &t2); cost[ch[0]-‘a‘] = min(t1,t2); } solve(); } return 0; }
时间: 2024-10-12 21:21:18