poj 3280 Cheapest Palindrome (dp)

http://poj.org/problem?id=3280

又是一道 dp 题目 一开是 有点 小思路,认为他就是括号匹配的变形吗,可是后来,越想月觉的麻烦,(后来才知道 自己 向的太多了,)

一开始 认为他 可以  在任意位置 插入和删除 有一定的费用 ,怎么个dp 法呀,后来看了解题报告 ,确实和 括号匹配一样,

我太菜了。。。。

题意: 一个字符串          求将其 变为回文串的最小花费 ,每个 字母  添加 和删除 都要一定的花费;

dp[i][j] 表示  将 str[i    -----j] 变为   回文串的最小花费

if(str[i] == str[j])   dp[i][j] = dp[i + 1][ j - 1];

els

{

     dp[i][j] = min(dp[i + 1][j] + min(add[str[i] - 'a'],dele[str[i ]- 'a']),dp[i][j -1] + min(add[str[j]- 'a'],dele[str[j ]- 'a']))  ;

}

 

转自别处:

其实dp很难逃出3种思路:

1、一维线性dp:每次考虑i时,选择最优子问题要么在i-1,要么在1...i-1里;

2、二维线性dp:考虑(i,j)子问题时,选择最优子问题要么在(i+1,j)、(i,j-1),要么在i<= k <=j,在k里;

3、树形dp:考虑i节点最优时,选择子节点最优,一般融合了01背包dp的双重dp。

上面3中模式也是我在做题后才发现的。

这个dp题其实就可以仿照第2中思路。

假设一个字符串Xx....yY;对于求这个字符串怎么求呢?

分4中情况讨论:

1、去掉X,取x....yY回文;

2、去掉Y,取Xx....y回文;

3、在左边加上X,取Xx....yYX回文;

4、在右边加上Y,取YXx....y回文。

至于去掉X、Y肯定没有第1、2中情况合算;加上X、Y肯定没有第3、4中情况合算。

因此令dp[i][j]为i...j要变成回文字符串的最小代价。

方程:

dp[i][j] = min{  dp[i+1][j] + {去掉X的代价},dp[i+1][j] + {加上X的代价},

                                                           dp[i][j-1]+ {去掉Y的代价},dp[i][j-1] +{加上Y的代价}};

其实分析发现,对于X而言,只要去 去掉 和加上 X 最小代价就行(因为前面dp串一样),Y同理。

因此最后得出:

dp[i][j] = min{  dp[i+1][j] +min{ {去掉X的代价}, {加上X的代价}},

                                                           dp[i][j-1]+min{ {去掉Y的代价}, {加上Y的代价}}};

dp时候还有些注意事项:

比如当X和Y字符一样时,则在dp时必须先为x...y的最小代价。

读取时也应注意。

 

 1     #include<cstdio>

 2     #include<cstring>

 3     #include<cmath>

 4     #include<iostream>

 5     #include<algorithm>

 6     #include<set>

 7     #include<map>

 8     #include<queue>

 9     #include<vector>

10     #include<string>

11     #define Min(a,b) a<b?a:b

12     #define Max(a,b) a>b?a:b

13     #define CL(a,num) memset(a,num,sizeof(a));

14     #define maxn  2050

15     #define eps  1e-6

16     #define inf 9999999

17     #define mx 1<<60

18 

19     using namespace std;

20     int add[maxn],dele[maxn];

21     int dp[maxn][maxn];

22     char str[maxn];

23     int main()

24     {

25         int  n , m,i,j ;

26         char c[3];

27         //freopen("dada.in","r",stdin);

28         while(~scanf("%d%d",&n,&m))

29         {

30             scanf("%s",str);

31             for(i = 0; i < n; ++i)

32             {

33                 scanf("%s",c);

34                 scanf("%d %d",&add[c[0] - 'a'],&dele[c[0] - 'a']);

35             }

36             int len = strlen(str);

37 

38             CL(dp,0);

39 

40             for( i = len - 2 ; i >= 0  ; -- i)

41             {

42                 for( j = i + 1; j < len ; ++j)

43                 {

44                     if(str[i] == str[j])  dp[i][j] =  dp[ i + 1][ j  - 1];

45                     else

46                     {

47                         dp[i][j] = min(dp[i + 1][j] + min(add[str[i] - 'a'],dele[str[i ]- 'a']),dp[i][j -1] + min(add[str[j]- 'a'],dele[str[j ]- 'a']))  ;

48                     }

49                 }

50             }

51 

52 

53             printf("%d\n",dp[0][len - 1]);

54 

55         }

56         return 0 ;

57     }

 

 

你可能感兴趣的:(heap)