题目大意:给你一个字符串,可以删除可以添加,并且每一次对一个字母的操作都带一个权,问你转成回文串最优操作数。
如果这一题我这样告诉你,你毫无疑问知道这一题是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]]};
参考:
1 #include2 #include 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 else45 {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 }