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 }

 

posted @ 2022-02-15 22:16  江上舟摇  阅读(28)  评论(0编辑  收藏  举报