nyoj 1023 还是回文(dp)

描述
判断回文串很简单,把字符串变成回文串也不难。现在我们增加点难度,给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费。那么,将字符串变成回文串的最小花费是多少呢?
输入
多组数据
第一个有两个数n,m,分别表示字符的种数和字符串的长度
第二行给出一串字符,接下来n行,每行有一个字符(a~z)和两个整数,分别表示添加和删除这个字符的花费
所有数都不超过2000
输出
最小花费
样例输入
3 4
abcb
a 1000 1100
b 350 700
c 200 800
样例输出

900

#include<cstdio>
#include<cstring>
#define N 2100
#define Min(a,b) (a>b?b:a)
using namespace std;
int cost[26],dp[N][N];
char str[N];
int main()
{
    int i,j,n,m,a,b;
    char s[2];
    while(~scanf("%d%d",&n,&m))
    {
        memset(dp,0,sizeof(dp));
        scanf("%s",str);
        for(i=0; i<n; i++)
        {
            scanf("%s%d%d",s,&a,&b);
            cost[s[0]-'a'] = Min(a,b);//两者选小的作为话费
        }
        for(j=1; j<m; j++)
        {
            for(i=j-1; i>=0; i--)
            {
                dp[i][j] = Min(dp[i+1][j]+cost[str[i]-'a'],dp[i][j-1]+cost[str[j]-'a']);//找每一个由小到大的区间,选最小话费的
                if(str[i] == str[j])
                    dp[i][j] = Min(dp[i+1][j-1],dp[i][j]);//状态定义为dp[i][j]:i到j这个区间形成回文的最小花费,如果已经匹配就不用加上花费
            }
        }
        printf("%d\n",dp[0][m-1]);

    }
}


你可能感兴趣的:(dp,动态规划,ACM,nyoj解题报告)