【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; }