标签:
题意:给你一个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;
}
poj 3280 Cheapest Palindrome DP
标签:
原文地址:http://www.cnblogs.com/sevenun/p/5441758.html