poj 3280 Cheapest Palindrome
题目链接:http://poj.org/problem?id=3280
不算是太好做,要想AC得付出一点时间。
如果只是求修改的最少次数,方法数将字符串s反转为s1,求二者的最长公共子序列之长L,用s的长度减去L即可。
但是这个题是求花费,所以这里采用区间内dp;
我们可以设dp[i][j]表示区间内i变成j的最小花费,用w[30]表示插入还是删除,其实都一样,插入无非是这头加,删除那头减,那么我们去这两者中花费较小的那一方就可以了。
那么开始考虑问题,有三种情况:
我们可以看到,如果s[i]=s[j]的话,那最小花费无非是dp[i][j]=dp[i+1][j-1];
如果是s[i+1]到s[j]是回文串
那dp[i][j]=dp[i+1][j]+w[i];
如果s[i]到s[j-1]是回文串
那么dp[i][j]=dp[i][j-1]+w[j];
那么转移方程就是dp[i][j]=min(dp[i+1][j]+w[i],dp[i+1][j]+w[i])
1 #include<iostream>//poj不能用万能头 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 int dp[2010][2010];//从子区间i到j要变成回文串索要花费的最少价值 7 char ch,s[2010];//修改字符和字符串 8 int w[30];//要修改单个字符所要花费的最小价值 9 int n,m,x,y; 10 int main() 11 { 12 while(cin>>n>>m) 13 { 14 cin>>s; 15 for(int i=0;i<n;i++) 16 { 17 cin>>ch>>x>>y;//读入每个字符的删除和插入花费 18 w[ch-'a']=min(x,y);//取其小 19 } 20 for(int len=1;len<m;len++)//区间长度 21 { 22 for(int i=0;i<=m-len;i++)//起点 23 { 24 int j=i+len;//终点 25 dp[i][j]=INT_MAX;//最小标兵最大值 26 if(s[i]==s[j])//参考三种情况 27 { 28 dp[i][j]=dp[i+1][j-1]; 29 }else 30 { 31 dp[i][j]=min(dp[i+1][j]+w[s[i]-'a'],dp[i][j-1]+w[s[j]-'a']); 32 } 33 } 34 } 35 cout<<dp[0][m-1]; 36 } 37 return 0; 38 }
本文来自博客园,作者:江上舟摇,转载请注明原文链接:https://www.cnblogs.com/LQS-blog/p/15898357.html