zoukankan      html  css  js  c++  java
  • 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     }
  • 相关阅读:
    apache安装遇到的问题
    babel+gulp实时转码ES6
    highcharts点击切换,不能自适应宽度
    多行文本溢出
    文件上传
    iscroll最后一个列表项无法显示出来
    curry化函数
    zepto中animate方法的使用注意
    js去除中间空格
    JS实现计算任意一个数的各个位数的和
  • 原文地址:https://www.cnblogs.com/acSzz/p/2633509.html
Copyright © 2011-2022 走看看