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
", dp[0][string_length - 1]);
52 }
原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/4832923.html