POJ 3280 Cheapest Palindrome(水题)
题意:给定一个完全由小写字母组成的字符串s,对每个字母比如x(或a,b,c...z),在字符串中添加或者删除它分别需要花费c1['x']和c2['x']的代价,问将给定字符串变成回文串所需要的最少代价为多少。
解法:设d[i][j]表示将字符串中从第i位至第j位变成回文串所需要的代价。若s[i] == s[j],d[i][j] = d[i+1][j-1];否则的话,有四种处理方法。
对xa.......by,可以将其变为xa......b,yxa.....by,a.......by,xa.....byx中的任意一种再处理。所以d[i][j] = min(d[i][j-1] + c2[s[j]], d[i][j-1] + c1[s[j]], d[i+1][j] + c2[s[i]], d[i+1][j] + c1[s[i]])。化简为d[i][j] = min(d[i][j-1] + min(c1[s[j]], c2[s[j]]), d[i+1][j] + min(c1[s[i]], c2[s[i]]))。(此公式看着没有化简,但实际上可以省很多代码,我的代码改了以后少了近200b)
tag:字符串,回文串,dp
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-17 21:44 4 * File Name: DP-POJ-3280.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <cstring> 9 #include <map> 10 #include <utility> 11 12 using namespace std; 13 14 #define CLR(x) memset(x, 0, sizeof(x)) 15 const int maxint = 2147483647; 16 17 char s[3000]; 18 int d[2005][2005]; 19 map<char, int > mp; 20 21 int main() 22 { 23 int n, len; 24 while (scanf ("%d%d", &n, &len) != EOF){ 25 scanf ("%s", s); 26 char x; 27 int t1, t2; 28 mp.clear(); 29 for (int i = 0; i < n; ++ i){ 30 x = 'P'; 31 while (!(x >= 'a' && x <= 'z')) scanf ("%c", &x); 32 scanf ("%d%d", &t1, &t2); 33 mp[x] = min(t1, t2); 34 } 35 36 CLR (d); 37 for (int i = 0; i < len; ++ i) 38 d[i][i] = 0; 39 for (int i = len-2; i >= 0; -- i) 40 for (int j = i+1; j < len; ++ j){ 41 if (s[i] == s[j]) d[i][j] = d[i+1][j-1]; 42 else 43 d[i][j] = min(maxint, min(d[i+1][j] + mp[s[i]], d[i][j-1] + mp[s[j]])); 44 } 45 printf ("%d\n", d[0][len-1]); 46 } 47 return 0; 48 }
------------------------------------------------------------------
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。
现在的你,在干什么呢?
你是不是还记得,你说你想成为岩哥那样的人。