【第七届蓝桥杯省赛C++A/C组】【区间DP】密码脱落

密码脱落

X星球的考古学家发现了一批古代留下来的密码。

这些密码是由A、B、C、D 四种植物的种子串成的序列。

仔细分析发现,这些密码串当初应该是前后对称的(也就是我们说的镜像串)。

由于年代久远,其中许多种子脱落了,因而可能会失去镜像的特征。

你的任务是:

给定一个现在看到的密码串,计算一下从当初的状态,它要至少脱落多少个种子,才可能会变成现在的样子。

输入格式
共一行,包含一个由大写字母ABCD构成的字符串,表示现在看到的密码串。

输出格式
输出一个整数,表示至少脱落了多少个种子。

数据范围
输入字符串长度不超过1000

输入样例1:

ABCBA

输出样例1:

0

输入样例2:

ABDCDCBABC

输出样例2:

3

思路分析:
res = 添几个字符变回文串 <-等价于-> 删几个字符变为回文串 <-等价于-> 总长度 - 最长回文子序列的长度

状态表示:
f[l][r] 表示所有s[l ~ r] 之间的回文子序列的集合的长度最大值
划分:
1. l和r都不在  f[l + 1][r - 1]
2. l在r不在    f[l][r - 1]
3. l不在r在    f[l + 1][r]
4. l和r都在    f[l + 1][r - 1] + 2
状态转移方程:
f[l][r] = max(f[l][r - 1], f[l + 1][r])
f[l][r] = max(f[l][r], f[l + 1][r - 1] + 2)
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 1010;
char s[N];
int f[N][N];

int main()
{
    
    
    scanf("%s", s);
    int n = strlen(s);
    
    for (int len = 1; len <= n; len ++)
        for (int l = 0; l + len - 1 < n; l ++)
        {
    
    
            int r = l + len - 1;
            if (len == 1) f[l][r] = 1;
            else
            {
    
    
                f[l][r] = max(f[l][r - 1], f[l + 1][r]);
                if (s[l] == s[r]) f[l][r] = max(f[l][r], f[l + 1][r - 1] + 2);
            }
        }
    cout << n - f[0][n - 1] << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/laaa123mmm/article/details/128990235
今日推荐