[区间DP练习] 求最长回文(不必连续)

1222. 密码脱落 - AcWing题库https://www.acwing.com/problem/content/1224/

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

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

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

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

你的任务是:

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

输入格式

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

输出格式

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

数据范围

输入字符串长度不超过1000

输入样例1:

ABCBA

输出样例1:

0

输入样例2:

ABDCDCBABC

输出样例2:

3
#include <cstdio>
#include <string.h>
using namespace std;

const int N = 1010;
int f[N][N];
char s[N];
int main()
{

    scanf("%s", s);
    
    int n = strlen(s);
    
    for(int i = 1; i <= n; i ++)
    {
        for(int l = 0; l+i-1 < n; l ++)
        {
            int r = l+i-1;
            if(i == 1) f[l][l] = 1;
            else{
                if(s[l] == s[r]) f[l][r] = f[l+1][r-1]+2;
                if(f[l+1][r] > f[l][r]) f[l][r] = f[l+1][r];
                if(f[l][r-1] > f[l][r]) f[l][r] = f[l][r-1];
            }
        }
    }
    
    printf("%d", n-f[0][n-1]);

    return 0;
}

1070. 括号配对 - AcWing题库https://www.acwing.com/problem/content/1072/

Hecy 又接了个新任务:BE 处理。

BE 中有一类被称为 GBE。

以下是 GBE 的定义:

  • 空表达式是 GBE
  • 如果表达式 A 是 GBE,则 [A] 与 (A) 都是 GBE
  • 如果 A 与 B 都是 GBE,那么 AB 是 GBE

下面给出一个 BE,求至少添加多少字符能使这个 BE 成为 GBE。

注意:BE 是一个仅由()[]四种字符中的若干种构成的字符串。

输入格式

输入仅一行,为字符串 BE。

输出格式

输出仅一个整数,表示增加的最少字符数。

数据范围

对于所有输入字符串,其长度小于100。

输入样例:

[])

输出样例:

1

法一(直接求最小):

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 110, INF = 1e8;
int f[N][N];
string s;
bool check(int l, int r)
{
    if(s[l] == '[' && s[r] == ']') return true;
    if(s[l] == '(' && s[r] == ')') return true;
    return false;
}
int main()
{
    cin >> s;
    
    int n = s.size();
    
    for(int len = 1; len <= n; len ++)
    {
        for(int l = 0; l+len-1 < n; l ++)
        {
            int r = l+len-1;
            f[l][r] = INF;
            if(check(l,r)) f[l][r] = f[l+1][r-1];
            if(r) f[l][r] = min(f[l][r], min(f[l+1][r], f[l][r-1])+1);
            
            for(int k = l; k < r; k ++)
                f[l][r] = min(f[l][r], f[l][k]+f[k+1][r]);
        }
    }
    cout << f[0][n-1];
    return 0;
}

法二(先求最大可以匹配的数量):

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 110, INF = 1e8;
int f[N][N];
string s;
bool check(int l, int r)
{
    if(s[l] == '[' && s[r] == ']') return true;
    if(s[l] == '(' && s[r] == ')') return true;
    return false;
}
int main()
{
    cin >> s;
    
    int n = s.size();
    
    for(int len = 2; len <= n; len ++)
    {
        for(int l = 0; l+len-1 < n; l ++)
        {
            int r = l+len-1;
            if(check(l,r)) f[l][r] = f[l+1][r-1]+2;

            for(int k = l; k < r; k ++)
                f[l][r] = max(f[l][r], f[l][k]+f[k+1][r]);
        }
    }
    cout << n-f[0][n-1];
    return 0;
}

 

posted @ 2022-03-19 17:50  泥烟  阅读(17)  评论(0编辑  收藏  举报