• 低价回文[区间dp]


    题目描述

    追踪每头奶牛的去向是一件棘手的任务,为此农夫约翰安装了一套自动系统。他在每头牛身上安装了一个电子身份标签,当奶牛通过扫描器的时候,系统可以读取奶牛的身份信息。目前,每个身份都是由一个字符串组成的,长度为M (1≤M≤2000),所有的字符都取自小写的罗马字母。

    奶牛们都是顽皮的动物,有时她们会在通过扫描器的时候倒着走,这样一个原来身份为abcb的奶牛就可能有两个不同的身份了(abcb和bcba),而如果身份是abcba的话就不会有这个问题了。

    约翰想改变奶牛们的身份,使他们不管怎么走读起来都一样。比如说,abcb可以在最后加个a,变成回文abcba;也可以在前面加上bcb,变成回文bcbabcb;或者去除字母a,保留的bcb也是一条回文。总之,约翰可以在任意位置删除或插入一些字符使原字符串变成回文。

    不巧的是,身份标签是电子做的,每增加或删除一个字母都要付出相应的费用(0≤代价≤10000)。给定一头奶牛的身份标签和增加或删除相关字母的费用,找出把原来字符串变成回文的最小费用。注意空字符串也是回文。

    输入格式

    第一行:两个用空格分开的整数:N和M 第二行:一个长度恰好为M的字符串,代表初始的身份标签 第三行到第N+2行:每行为一个用空格分开的三元组:其中包括一个字符和两个整数,分别表示增加或删除这个字符的费用

    输出格式

    第一行:只有一个整数,表示改造这个身份标签的最小费用

    样例

    样例输入

    3 4 
    abcb
    a 1000 1100
    b 350 700
    c 200 800
    

    样例输出

    900
    

    思路

    我们看一下样例, abcb, 其中 bcb 已经是回文, 我们需要更改 a

    我们既可以把a删去, 也可以在后面加一个a

    因此, 更改a的代价, 为 加上他的代价删去他的代价 中的 最小值

    当 ch[i] == ch[j] 时, 得方程

    dp[i][j] = min(dp[i+1][j]+v[ch[i]], dp[i][j-1]+v[ch[j]]);

    其中dp[i][j]为把 i-j 变成回文的最小代价

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int maxn = 1e4+10;
    int dp[maxn][maxn], a[maxn], v[maxn];
    char ch[maxn], now[2];
    int main(){
        int n, m, x, y; scanf("%d%d", &n, &m);
        scanf("%s", ch+1);
        for(int i=1; i<=n; i++){
            scanf("%s%d%d", now, &x, &y);
            v[now[0]] = min(x, y);
        }
        for(int j=2; j<=m; j++)
            for(int i=j-1; i>=1; i--){
                dp[i][j] = 0x3f3f3f3f;
                if(ch[i]==ch[j]) dp[i][j] = dp[i+1][j-1];
                else dp[i][j] = min(dp[i+1][j]+v[ch[i]], dp[i][j-1]+v[ch[j]]);
            }
        printf("%d
    ", dp[1][m]);
        return 0;
    }
    
  • 相关阅读:
    丁丁又病了
    领导之所以是领导
    丁丁的进步
    最近比较烦
    批量更新数据表
    转帖:《EnterLib PIAB深入剖析》系列博文汇总
    XML DOM介绍
    转大白话系列之C#委托与事件讲解大结局
    using
    jQuery工作原理解析以及源代码示例
  • 原文地址:https://www.cnblogs.com/hzoi-poozhai/p/12896754.html
Copyright © 2020-2023  润新知