Cheapest Palindrome POJ - 3280

原题链接

考察:区间dp

递推思路:

       套区间dp模板,划分集合的时候分为增加或者减少 f[i][j]为当前区间为[i,j]时变为回文串的最小花费.

       就和密码脱离那道题差不多,if s[i] = s[j] f[i][j] = f[i+1][j-1].

                                                  else f[i][j] = min(f[i+1][j]+cost,f[i][j],f[i][j-1]+cost,f[i][j])分别对应使s[i]、s[j]对称.

       我写的繁琐了,其实增加和删除的花费选一个最小的就行了.

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 const int N = 2010,M = 30,INF = 0x3f3f3f3f;
 7 int ad[M],de[M],f[N][N],m;
 8 char s[N];
 9 void solve()
10 {
11     for(int len=2;len<=m;len++)
12         for(int i=1;i+len-1<=m;i++)
13         {
14             int j = i+len-1;
15             f[i][j] = INF;
16             if(s[i]==s[j]) f[i][j] = f[i+1][j-1];
17             else{
18                 int a = de[s[i]-'a'],b = de[s[j]-'a'];
19                 int c = ad[s[i]-'a'],d = ad[s[j]-'a'];
20                 f[i][j] = min(f[i+1][j]+a,f[i][j]);
21                 f[i][j] = min(f[i][j-1]+b,f[i][j]);
22                 f[i][j] = min(f[i+1][j]+c,f[i][j]);
23                 f[i][j] = min(f[i][j-1]+d,f[i][j]);
24             }
25         }
26 }
27 int main()
28 {
29     int n;
30     scanf("%d%d%s",&n,&m,s+1);
31     for(int i=1;i<=n;i++)
32     {
33         int d1,d2;char c[2]; 
34         scanf("%s%d%d",c,&d1,&d2);
35         ad[c[0]-'a'] = d1,de[c[0]-'a'] = d2;
36     }
37     solve();
38     printf("%d\n",f[1][m]);
39     return 0;
40 }

 

posted @ 2021-02-18 23:26  acmloser  阅读(46)  评论(0编辑  收藏  举报