POJ3280 Cheapest Palindrome 区间DP

好久不做DP了。。。

题意:求原串通过删除和添加某些字符构成回文串的最小代价

设f[i][j]表示i到j位匹配的最小代价,那么有

f[i][j]=Inf;
if(ch[i]==ch[j]) f[i][j]=f[i+1][j-1];
f[i][j]=min(f[i][j],f[i][j-1]+min(vl[ch[j]][1],vl[ch[j]][0]));
f[i][j]=min(f[i][j],f[i+1][j]+min(vl[ch[i]][1],vl[ch[i]][0]));    

其中vl[char][0/1]表示添加或删除char 的代价

#include<cstdio>
#include<iostream>
#define R register int
const int Inf=0x3f3f3f3f;
using namespace std;
inline int g() {
    R ret=0,fix=1; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,f[2010][2010];
int vl[128][2];
char ch[2010];
signed main() {
    n=g(),m=g();
    for(R i=1;i<=m;++i) ch[i]=getchar();
    for(R i=1;i<=n;++i) {
        register char ch;
        while(!isalpha(ch=getchar()));
        vl[(int)ch][0]=g(),vl[(int)ch][1]=g();
    }
    //for(R i='a';i<='z';++i) cout<<vl[i][0]<<" "<<vl[i][1]<<endl;
    for(R l=2;l<=m;++l) for(R i=1,j=l;j<=m;++i,++j) {
        f[i][j]=Inf;
        if(ch[i]==ch[j]) f[i][j]=f[i+1][j-1];
        f[i][j]=min(f[i][j],f[i][j-1]+min(vl[ch[j]][1],vl[ch[j]][0]));
        f[i][j]=min(f[i][j],f[i+1][j]+min(vl[ch[i]][1],vl[ch[]][0]));    
    } printf("%d\n",f[1][m]);
}

2019.04.06

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/10660860.html