DP:Cheapest Palindrome(POJ 3280)
题目大意:给你一个字符串,可以删除可以添加,并且每一次对一个字母的操作都带一个权,问你转成回文串最优操作数。
如果这一题我这样告诉你,你毫无疑问知道这一题是LD(Levenshtien Distance 编辑距离),但是上面太多废话了,理解起来还是要有点费劲,比如我一开始就觉得回文串只能从头或者尾添加(英语吃了翔╮(╯▽╰)╭)。
好吧,其实这一题不是水题(我的感觉),这一题挺好的,是一个带权的编辑距离问题,因为最后还是老问题,问你最小值,所以马上想到用二维矩阵,但是这一题首先要解决两个陷阱。
第一个陷阱就是题目回文串,其实这一题和回文串关系都没有,就是在基准状态(空串或者一个字母的时候用到)。
第二个陷阱就是删除和加入的问题,你仔细看一下题目给的条件,你会发现这两个权都是正的,这说明这两个操作都是等效的(有点像LD),最后要你找到最小值,所以我们只用关注最小的那个值就可以了
但是回文串我们不可能全部枚举出来,而且LD要求的是固定字串,那么怎么办?其实我们可以这样,从最小开始,一个一个小串找,反正删除和加入都是等价操作,我们可以把这些操作的最小操作数都记录下来,那么最后要求的值就在dp[0][length-1]上了
状态转移方程几乎和LD是一样的,只是少了input[j]!=input[i]时,与dp[i+1][j-1]的比较(这相当于修改了,修改也就是删除+加入,肯定不合理)
dp[i][j]=dp[i+1][j-1]; input[i]==input[j];
dp[i][j]=min{min(dp[i+1][j]+add[input[i]],dp[i][j]),dp[i][j-1]+add[input[j]]};
参考:http://blog.csdn.net/y990041769/article/details/24259569
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define MAX_N 2001 4 #define MIN(a,b) ((a)<(b)?(a):(b)) 5 6 static int word_dist[26]; 7 static char input[MAX_N]; 8 static int dp[MAX_N][MAX_N]; 9 10 void Search(const int, const int); 11 12 int main(void) 13 { 14 int string_length, c_word_sum, i, tmp_add, tmp_de; 15 char tmp; 16 17 while (~scanf("%d%d", &c_word_sum, &string_length)) 18 { 19 getchar();//除掉回车 20 scanf("%s", input); 21 for (i = 0; i < c_word_sum; i++) 22 { 23 getchar();//除掉回车 24 scanf("%c", &tmp); 25 scanf("%d%d", &tmp_add, &tmp_de); 26 word_dist[tmp - 'a'] = MIN(tmp_add, tmp_de); 27 } 28 Search(string_length, c_word_sum); 29 } 30 return 0; 31 } 32 33 void Search(const int string_length, const int c_word_sum) 34 { 35 //最后最小值会继承到dp[0][string_length - 1] 36 int i, j, k; 37 for (i = 1; i < string_length; i++) 38 { 39 for (j = 0, k = i; k < string_length; j++, k++) 40 { 41 dp[j][k] = INT_MAX; 42 if (input[j] == input[k]) 43 dp[j][k] = dp[j + 1][k - 1]; 44 else 45 { 46 dp[j][k] = MIN(dp[j + 1][k] + word_dist[input[j] - 'a'], dp[j][k]); 47 dp[j][k] = MIN(dp[j][k - 1] + word_dist[input[k] - 'a'], dp[j][k]); 48 } 49 } 50 } 51 printf("%d\n", dp[0][string_length - 1]); 52 }