1 条题解

  • 0
    @ 2025-8-24 21:56:03

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Elegia
    irony

    搬运于2025-08-24 21:56:03,当前版本为作者最后更新于2018-01-07 14:32:20,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    考虑进行动态规划。

    令状态dp[i][j][k]表示目前A串已经匹配了前ii个字符,B串已经匹配了前jj个字符,kk代表是否末尾的空格位置。两个都是空格显然不是一个优解,因为把这两个都去掉就必然会使得相似度增加。

    kk只有代表3种可能:没有空格/在A串/在B串。

    如果此状态没有任何空格即k=0k=0,就直接从dp[i - 1][j - 1][]中最大相似值转移。如果在其中一个位置,那么就要考虑到上一个空格的位置在哪,我们不妨认为每段空格的第一个需要支付a-a的代价,后面的都需要支付b-b的代价,就很自然地列出了方程dp[i][j][1] = max{dp[i][j - 1][1] - b, dp[i][j - 1][0] - a, dp[i][j - 1][2] - a}

    dp[i][j][2]的原理是对称的。

    答案在dp[n][m][]中取得。

    注意一些边界问题。

    #include <climits>
    #include <cstdio>
    #include <cstring>
    
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 3010;
    
    int n, m, a, b;
    int x[N], y[N], mp[256];
    int d[4][4];
    char s[N];
    
    ll dp[N][N][3];
    
    int main() {
        mp['A'] = 0;
        mp['T'] = 1;
        mp['G'] = 2;
        mp['C'] = 3;
        scanf("%s", s + 1);
        n = strlen(s + 1);
        for (int i = 1; i <= n; ++i)
            x[i] = mp[s[i]];
        scanf("%s", s + 1);
        m = strlen(s + 1);
        for (int i = 1; i <= m; ++i)
            y[i] = mp[s[i]];
        for (int i = 0; i < 4; ++i)
            for (int j = 0; j < 4; ++j)
                scanf("%d", &d[i][j]);
        scanf("%d%d", &a, &b);
        for (int i = max(n, m); i; --i) {
            dp[0][i][0] = dp[i][0][0] = dp[0][i][2] = dp[i][0][1] = -(1LL << 60);
            dp[0][i][1] = dp[i][0][2] = -a - b * (i - 1);
        }
        dp[0][0][1] = dp[0][0][2] = -(1LL << 60);
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= m; ++j) {
                dp[i][j][0] = *max_element(dp[i - 1][j - 1], dp[i - 1][j - 1] + 3) + d[x[i]][y[j]];
                dp[i][j][1] = max(max(dp[i][j - 1][0] - a, dp[i][j - 1][1] - b), dp[i][j - 1][2] - a);
                dp[i][j][2] = max(max(dp[i - 1][j][0] - a, dp[i - 1][j][2] - b), dp[i - 1][j][1] - a);
            }
        printf("%lld\n", *max_element(dp[n][m], dp[n][m] + 3));
        return 0;
    }
    
    • 1

    信息

    ID
    3021
    时间
    1000ms
    内存
    500MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者