• Cheapest Palindrome [POJ3280] [区间DP] [经典]


    一句话题意:每个字母添加和删除都相应代价(可以任意位置 增加/删除),求把原串变成回文串的最小代价

    Description

    保持对所有奶牛的跟踪是一项棘手的任务,因此农场主约翰已经安装了一个系统来实现自动化。他在每头奶牛身上安装了一个电子ID标签,系统将在奶牛经过扫描仪时读取。每个ID标记是从字母表中提取的一个字符串。

    奶牛,它们是淘气的动物,有时试图通过倒着走来欺骗系统。如果一头奶牛的ID是“abcba”,那么无论她怎么走,它都能读到同样的东西,而拥有“abcb”的奶牛可能会注册为两个不同的ID(“abcb”和“bcba”)。

    FJ希望改变奶牛的ID标签,这样无论奶牛走过哪个方向,他们都能读到同样的标签。例如,“abcb”可以通过在末尾添加“a”来改变,从而形成“abcba”,这样ID就会是一个回文串。更改ID的其他一些方法包括将三个字母“bcb”添加到“abcb”的开始,以获得ID“bcbabcb”或删除字母“a”以产生ID“bcb”。我们可以在字符串中的任意位置添加或删除字符,其长度比原来的字符串长或短。

    不幸的是,ID标签是电子信息,每个字符插入或删除都有代价,这取决于要添加或删除的字符值。考虑到奶牛ID标签的内容以及插入或删除字母表中的每个字符的成本,找到更改ID标记的最小成本,从而满足FJ的需求。一个空的ID标签被认为满足了读取前后相同的要求。只有带有相关成本的字母才能添加到字符串中。

    Input

    Line 1: 两个空间分隔的整数:N和M (1 ≤ M ≤ 2,000) (1 ≤ N ≤ 26)
    Line 2: 这一行包含了组成初始ID字符串的M个字符
    Lines 3.. N+2: 每行包含三个空间分隔的实体:输入字母和两个整数的字符,分别是添加和删除该字符的成本(Ci<=10000)。
    Output
    Line 1: 单个整数的一行,这是更改给定名称标签的最小代价。
    Sample Input
    3 4
    abcb
    a 1000 1100
    b 350 700
    c 200 800
    Sample Output
    900
    Hint
    如果我们在最后插入一个“a”,得到“abcba”,成本是1000。如果我们在开始的时候删除“a”,就会得到“bcb”,代价就是1100。如果我们在字符串的开始处插入“bcb”,代价将是350 + 200 + 350 = 900,这是最小值。
    Solution
    首先,这是一个很明显的区间问题
    如果一个区间[i,j]已经是回文序列了,就很好处理。
    那我们设dp[i][j]为,使区间[i,j]成为回文序列的最小代价
    当s[i-1]==s[j+1]时,dp[i+1][j-1]=dp[i][j]
    其他情况:dp[i-1][j]=dp[i][j]+min(del[s[i-1]],add[s[i-1]])
         dp[i][j+1]=dp[i][j]+min(del[s[j+1]],add[s[j+1]])
    tips:我们输入的时候就保留增加和减小的最小值
    Code
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #define RG register int
     6 #define rep(i,a,b)    for(RG i=a;i<=b;i++)
     7 #define per(i,a,b)    for(RG i=a;i>=b;i--)
     8 #define inf (1<<30)
     9 using namespace std;
    10 int n,m;
    11 int val[130],dp[2005][2005];
    12 char s[2005];
    13 inline int read()
    14 {
    15     int x=0,f=1;char c=getchar();
    16     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    17     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    18     return x*f;
    19 }
    20 
    21 void DP()
    22 {
    23     rep(k,2,m)
    24     {
    25         for(RG i=1,j=k;j<=m;j++,i++)
    26         {
    27             dp[i][j]=inf;
    28             if(s[i]==s[j])    dp[i][j]=dp[i+1][j-1];
    29             else
    30             {
    31                 dp[i][j]=min(dp[i][j],dp[i+1][j]+val[s[i]]);
    32                 dp[i][j]=min(dp[i][j],dp[i][j-1]+val[s[j]]);
    33             }
    34         }
    35     }
    36     printf("%d",dp[1][m]);
    37 }
    38 
    39 int main()
    40 {
    41     char ch;int x,y;
    42     n=read(),m=read();
    43     scanf("%s",s+1);
    44     rep(i,1,n)    cin>>ch,x=read(),y=read(),val[ch]=min(x,y);
    45     DP();
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    mysql日期计算转换
    Mysql的DATE_FORMAT()日期格式转换
    JDBC连接池BoneCP
    JSP之三大指令
    JSP的三大指令 七大动作 九大对象
    JSP的语法
    orcale序列操作
    Orcale约束-------外键约束
    Orcale约束-------檢查約束
    Orcale约束-------主键约束
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9210988.html
Copyright © 2020-2023  润新知