标签:
http://poj.org/problem?id=3280
n 种小写字母构成长度为 m 的串,现在要通过增删字母使串回文,给出每种字母增和删的费用,求最小花费.
用 dp [ i ][ j ]表示使i~j区间回文的最小画费.
1.如果 a [ i ] == a [ j ] 那么要让 i ~ j 回文只需要处理 ( i+1 ) ~ ( j-1 )即可,所以 dp [ i ][ j ] = dp [ i+1 ][ j-1 ].
2.其他情况就用如下递推关系:
dp [ i ][ j ] = min ( dp [ i+1 ][ j ] + cost [ a [ i ] ] , dp [ i ][ j-1 ] + cost [ a[ j ] ] )
如果从回文的 ( i+1 ) ~ j 而来,添加了 a [ i ] 后就不回文了, 可以再在右边加一个 a[ i ] ,或者删掉左边的 a [ i ] ,所以 cost [ a [ i ] ] 取增删中最小的即可, i ~ ( j-1 ) 同理.
#include<cstdio> #include<algorithm> #define read(a) a=getnum() using namespace std; const int maxn=26,maxm=2005; int n,m; int a[maxm],cost[maxn]; int dp[maxm][maxm]; inline int getnum() { int ret=0,k=1;char c; for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()) if(c==‘-‘) k=-1; for(;c>=‘0‘&&c<=‘9‘;c=getchar()) ret=ret*10+c-‘0‘; return ret*k; } void solve() { for(int i=m;i>=1;i--) { for(int j=i;j<=m;j++) { if(a[i]==a[j]) dp[i][j]=dp[i+1][j-1]; else dp[i][j]=min(dp[i+1][j]+cost[a[i]],dp[i][j-1]+cost[a[j]]); } } printf("%d\n",dp[1][m]); } void init() { read(n); read(m); char c; for(int i=1;i<=m;i++) { c=getchar(); a[i]=c-‘a‘; } getchar(); for(int i=1;i<=n;i++) { int c1,c2; c=getchar(); read(c1); read(c2); cost[c-‘a‘]=min(c1,c2); } } int main() { #ifndef ONLINE_JUDGE freopen("cheap.in","r",stdin); freopen("cheap.out","w",stdout); #endif init(); solve(); #ifndef ONLINE_JUDGE fclose(stdin); fclose(stdout); system("cheap.out"); #endif return 0; }
标签:
原文地址:http://www.cnblogs.com/Sunnie69/p/5432672.html