码迷,mamicode.com
首页 > 其他好文 > 详细

[USACO07OPEN]便宜的回文题解

时间:2019-12-07 01:01:36      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:区间dp   cst   题目   情况   space   代码   字符   ret   i+1   

欢迎来看看呀

题目链接

一道十分巧妙的区间DP题

首先我们必须要发现一个重要的性质,不然状态转移方程会十分的复杂,那么就是删除一个字符和增加一个字符的效果是等价的

举个栗子,我们现在有一个字符串abccbdpl,要将a[bccbd]pl括起来的一段字符变成回文

变成[dbccbd]和[bccb]对后面所造成的影响是一样的,所以增加或删除一个字符\(i\)的最小代价\(cost[i]\)变为\(min(add[i],del[i])\)

然后便可以只考虑添加字符的情况,\(dp[i][j]\)表示将位置为\(i\)\(j\)的字符变成回文串的代价,枚举i和j

如果此时的\(s[i]\)=\(s[j]\),\(dp[i][j]=min(dp[i][j],dp[i+1][j-1])\)

\(s[i]!=s[j]\),\(dp[i][j]=min(dp[i][j-1]+cost[j],dp[i+1][j]+cost[i])\)

还要注意一下边界问题,\(dp[i][i]=0,dp[i][i-1]=0\),其他的都要初始化为极大值

代码

#include<iostream>
#include<cstdio>
using namespace std;
int n,m,mp[400],f[2003][2003],a,b,r;
char a1[2003],p;
int main()
{
    scanf("%d%d%s",&n,&m,&a1);
    for(int i=1; i<=n; i++)
    {
        cin>>p;
        scanf("%d%d",&a,&b);
        mp[p]=min(a,b);
    }
    for(int i=0; i<m; i++)
        for(int j=i+1; j<m; j++)
            f[i][j]=1e9;
    for(int i=1; i<m; i++)
    {
        for(int j=0; j+i<m; j++)
        {
            r=j+i;
            f[j][r]=min(f[j+1][r]+mp[a1[j]],f[j][r-1]+mp[a1[r]]);
            if(a1[j]==a1[r])
            f[j][r]=min(f[j][r],f[j+1][r-1]);
        }
    }
    cout<<f[0][m-1];
    return 0;
}

[USACO07OPEN]便宜的回文题解

标签:区间dp   cst   题目   情况   space   代码   字符   ret   i+1   

原文地址:https://www.cnblogs.com/dzice/p/12000179.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!