【BZOJ】1710: [Usaco2007 Open]Cheappal 廉价回文

【算法】区间DP

【题解】回文问题的套路做法:区间DP。

f[i][j]表示区间i~j回文的最小代价,则有f[i][j]=min{①②③}。

①f[i+1][j]+min(a[s[i]],b[s[i]])

②f[i][j-1]+min(a[s[j]],b[s[j]])

③f[i+1][j-1],s[i]==s[j]

注意初始化,f[i][i]=f[i][i+1]=f[i+1][i]=0,偶数回文时初始状态会交错。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=2010;

int n,m,s[maxn],a[30],f[maxn][maxn];
char ss[maxn];
int main(){
    scanf("%d%d%s",&n,&m,ss+1);
    for(int i=1;i<=m;i++)s[i]=ss[i]-'a';
    int b,c;
    for(int i=1;i<=n;i++){
        scanf("%s",ss+1);
        scanf("%d%d",&b,&c);
        a[ss[1]-'a']=min(b,c);
    }
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=m;i++)f[i][i]=0,f[i][i+1]=f[i+1][i]=0;//
    for(int p=2;p<=m;p++){
        for(int i=1;i<=m-p+1;i++){
            int j=i+p-1;
            f[i][j]=min(f[i+1][j]+a[s[i]],f[i][j-1]+a[s[j]]);
            if(s[i]==s[j])f[i][j]=min(f[i][j],f[i+1][j-1]);
        }
    }
    printf("%d",f[1][m]);
    return 0;
}
View Code

 

posted @ 2017-09-26 10:15  ONION_CYC  阅读(233)  评论(0编辑  收藏  举报