经典DP。影响决策的是字符串的内容。而添加和删除字符本质上是一样的,我们不管选择哪一种都可以,所以只需要取两者中费用最小的。
状态转移方程就是:
if(s[i]==s[j]) dp[i][j] = dp[i+1][j-1];
else dp[i][j] = min(dp[i+1][j]+w[s[i]-‘a‘],dp[i][j-1]+w[s[j]-‘a‘]);
其中dpd[i][j]表示从字符串的i-j段为回文串时的最小值。
值得注意的是i需要反向枚举,j需要正向枚举,这是由状态转移的顺序决定的。因为dp[i][j]需要借用i+1时的结果和j+1时的结果。
#include<cstdio> #include<algorithm> using namespace std; int n,m,w[30],dp[2005][2005]; char s[2005]; int main() { scanf("%d%d",&n,&m); scanf("%s",s); char c = getchar(); int a,b; for(int i=0;i<n;i++) { c = getchar(); scanf("%d%d",&a,&b); int d = min(a,b); w[c-'a'] = d; c = getchar(); } for(int i=m-1;i>=0;i--) for(int j=i+1;j<m;j++) { if(s[i]==s[j]) dp[i][j] = dp[i+1][j-1]; else dp[i][j] = min(dp[i+1][j]+w[s[i]-'a'],dp[i][j-1]+w[s[j]-'a']); } printf("%d\n",dp[0][m-1]); return 0; }
Cheapest Palindrome.(POJ-3280)
原文地址:http://blog.csdn.net/weizhuwyzc000/article/details/45152881