洛谷题单指南-动态规划3-P1140 相似基因

原题链接:https://www.luogu.com.cn/problem/P1140

题意解读:两个只包含A、C、G、T4个字符的序列,根据已经定义好的字符-字符的相似度,计算两个序列最大的相似度,两个序列必须每个字符都配对,如果字符不够,可以插入'-'代替。

解题思路:

本题要解决几个问题:

1、状态表示

既然有两个序列,设分别为a[n]、b[m],很容易想到设dp[i][j]表示a序列1~i和b序列1~j的相似度

为了方便查表计算字符-字符对应的相似度,可以将'A'、'C'、'G'、'T'、'-'转换为0,1,2,3,4

这样可以用二维数组保存所有的相似度关系:

int s[5][5] =  
{
    5, -1, -2, -1, -3,
    -1, 5, -3, -2, -4,
    -2, -3, 5, -2, -2,
    -1, -2, -2, 5, -1,
    -3, -4, -2, -1, 0
};

2、状态转移

对与a[1~i]和b[1~j],重点考虑最后一个字符的配对关系,有三种可能:

a[i]和b[j]配对:dp[i][j] = dp[i-1][j-1] + s[a[i]][b[j]]

在a[i]后面插入'-',用'-'和b[i]配对:dp[i][j] = dp[i][j-1] + s[4][b[j]]

在b[i]后面插入'-',用a[i]和'-'配对:dp[i][j] = dp[i-1][j] + s[a[i]][4]

以上三种情况取max即可

3、初始化

由于i,j都从1开始枚举,而递推式中会依赖于i-1,j-1,因此要对dp[i][0]以及dp[0][i]进行初始化

dp[i][0]表示a[1~i]与空串的相似度,就是a中每个字符与'-'配对的相似度之和

dp[0][i]表示空串与b[1~i]的相似度,就是'-'与b中每个字符配对的相似度之和

dp[0][0]保持0即可,没有配对发生

4、结果

dp[n][m]

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 105;
int n, m;
int a[N], b[N]; //对应两组碱基序列, A,C,G,T分别对应0,1,2,3,-对应4
int dp[N][N]; //dp[i][j]表示a序列1~i和b序列1~j的相似度
int s[5][5] =   //碱基之间的相似度
{
    5, -1, -2, -1, -3,
    -1, 5, -3, -2, -4,
    -2, -3, 5, -2, -2,
    -1, -2, -2, 5, -1,
    -3, -4, -2, -1, 0
};

int getnum(char x)
{
    if(x == 'A') return 0;
    if(x == 'C') return 1;
    if(x == 'G') return 2;
    if(x == 'T') return 3;
    if(x == '-') return 4;
}

int main()
{
    char x;
    cin >> n;
    for(int i = 1; i <= n; i++)
    {
        cin >> x;
        a[i] = getnum(x);
    }
    cin >> m;
    for(int i = 1; i <= m; i++)
    {
        cin >> x;
        b[i] = getnum(x);
    }

    for(int i = 1; i <= n; i++)
    {
        dp[i][0] = dp[i-1][0] + s[a[i]][4]; //初始化所有的dp[i][0]为a:1~i对应'-'的相似度之和
    }
    for(int i = 1; i <= m; i++)
    {
        dp[0][i] = dp[0][i-1] + s[4][b[i]]; //初始化所有的dp[0][i]为'-'对应b:1~i的相似度之和
    }

    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            dp[i][j] = max(dp[i-1][j-1] + s[a[i]][b[j]], max(dp[i][j-1] + s[4][b[j]], dp[i-1][j] + s[a[i]][4]));
        }
    }
    cout << dp[n][m];

    return 0;
}

 

posted @ 2024-05-13 18:00  五月江城  阅读(23)  评论(0编辑  收藏  举报