Cheapest Palindrome POJ - 3280
考察:区间dp
递推思路:
套区间dp模板,划分集合的时候分为增加或者减少 f[i][j]为当前区间为[i,j]时变为回文串的最小花费.
就和密码脱离那道题差不多,if s[i] = s[j] f[i][j] = f[i+1][j-1].
else f[i][j] = min(f[i+1][j]+cost,f[i][j],f[i][j-1]+cost,f[i][j])分别对应使s[i]、s[j]对称.
我写的繁琐了,其实增加和删除的花费选一个最小的就行了.
1 #include <iostream> 2 #include <algorithm> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 const int N = 2010,M = 30,INF = 0x3f3f3f3f; 7 int ad[M],de[M],f[N][N],m; 8 char s[N]; 9 void solve() 10 { 11 for(int len=2;len<=m;len++) 12 for(int i=1;i+len-1<=m;i++) 13 { 14 int j = i+len-1; 15 f[i][j] = INF; 16 if(s[i]==s[j]) f[i][j] = f[i+1][j-1]; 17 else{ 18 int a = de[s[i]-'a'],b = de[s[j]-'a']; 19 int c = ad[s[i]-'a'],d = ad[s[j]-'a']; 20 f[i][j] = min(f[i+1][j]+a,f[i][j]); 21 f[i][j] = min(f[i][j-1]+b,f[i][j]); 22 f[i][j] = min(f[i+1][j]+c,f[i][j]); 23 f[i][j] = min(f[i][j-1]+d,f[i][j]); 24 } 25 } 26 } 27 int main() 28 { 29 int n; 30 scanf("%d%d%s",&n,&m,s+1); 31 for(int i=1;i<=n;i++) 32 { 33 int d1,d2;char c[2]; 34 scanf("%s%d%d",c,&d1,&d2); 35 ad[c[0]-'a'] = d1,de[c[0]-'a'] = d2; 36 } 37 solve(); 38 printf("%d\n",f[1][m]); 39 return 0; 40 }