HDOJ1080 基因序列相似度(动态规划)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1080

题目大意:基因序列里面有四个字符ACTG,对于个基因序列,从中插入“-”符号让两个基因序列一样长。对于ACGT-这五个符号,任意两个符号都有一个对应的得分,给定一个对应符号的得分矩阵,求两个基因序列插入-符号以后得分的最大值。

例如:AGTGATG和GTTAG这两个基因序列,插入-符号使两个基因序列等长,AGTGAT-G和-GT--TAG是其中一种方案,在这种方案中,A对应-,G对应G,T对应T,G对应-,A对应-。。。。。。。根据对应元素的矩阵计算总得分。我们的目标是计算得分的最大值。

本题如果暴力解,列出所有可能插入-符号的情况,计算量非常大,根本行不通,而且会产生大量的子问题的重复计算。所以本题选用动态规划的方法来做。

首先,动态规划问题都是做出某种选择(一般通过遍历来确定哪种选择是最优的选择),确定了规模更小的子问题。通过子问题构建和原问题的递推关系式,进而求解原问题(一般采取自底向上的方法)。

我们以TAGCTAG和ATTGC这两个基因序列为例,设f[i][j]表示第一个序列前i个元素和第二个序列前j个元素的最大得分,我们的目标是求f[7][5]。当插入-符号两个序列等长以后,最后一个元素只有三种可能:

1、G对应C,此时产生子问题f[6][4]。此时f[7][5]=GC对应的分数+f[6][4]

2、G对应-,此时产生子问题f[6][5]。此时f[7][5]=G-对应的分数+f[6][5]

3、-对应C,此时产生子问题f[7][4]。此时f[7][5]=-C对应的分数+f[7][4]

f[7][5]等于三者的最大值。

采用自底向上求解的过程中,f[0][i]和f[i][0](i任意)所为初始条件,f[0][0]=0,举个例子f[0][2]就等于--和AT的得分(由于第一个序列没有元素)。

扫描二维码关注公众号,回复: 4921981 查看本文章

附上我的求解程序:

#include<iostream>
#include<string>
#include<climits>
using namespace std;
#define DEBUG
#define MAX(a,b) (a)>(b)?(a):(b)

//A:0,C:1,G:2,T:3,-:4
int score_matrix[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,INT_MIN},
};

int T;
int f[105][105];//f[i][j]表示gene[0]的前i个元素和gene[1]的前j个元素最大数
void initf(int& len0,string& gen0,int& len1,string& gen1);
int getIndex(char ch);

int main(){
    cin>>T;
    int len[2];
    string gene[2];
    string s;
    while(T--){
        cin>>len[0]>>gene[0]>>len[1]>>gene[1];
        initf(len[0],gene[0],len[1],gene[1]);

        string::iterator iter0=gene[0].begin();
        string::iterator iter1=gene[1].begin();
        char char0,char1;
        int x,y;
        for(int i=1;i<=len[0];i++){
            for(int j=1;j<=len[1];j++){
                //计算f[i][j],gene[0]的前i个字符和gene[1]的前j个字符的最大值
                char0=*(iter0+i-1);//gene[0]第i个字符
                char1=*(iter1+j-1);//gene[1]第j个字符
                x=getIndex(char0);
                y=getIndex(char1);
                f[i][j]=MAX(f[i][j],f[i-1][j-1]+score_matrix[x][y]);
                f[i][j]=MAX(f[i][j],f[i-1][j]+score_matrix[x][4]);
                f[i][j]=MAX(f[i][j],f[i][j-1]+score_matrix[y][4]);
            }
        }
        cout<<f[len[0]][len[1]]<<endl;
    }
}

void initf(int& len0,string& gen0,int& len1,string& gen1){
    for(int i=0;i<105;i++){
        for(int j=0;j<105;j++)
            f[i][j]=INT_MIN;
    }
    f[0][0]=0;
    string::iterator iter=gen1.begin();
    for(int i=1;i<=len1;i++){
        //计算f[0][i]
        int tmp_index=getIndex(*iter);
        f[0][i]=f[0][i-1]+score_matrix[4][tmp_index];
        iter++;
    }
    iter=gen0.begin();
    for(int i=1;i<=len0;i++){
        //计算f[i][0]
        int tmp_index=getIndex(*iter);
        f[i][0]=f[i-1][0]+score_matrix[4][tmp_index];
        iter++;
    }

}
int getIndex(char ch){
    switch(ch){
        case 'A':return 0;
        case 'C':return 1;
        case 'G':return 2;
        case 'T':return 3;
        default:return 4;
    }
}

猜你喜欢

转载自blog.csdn.net/LOVETEDA/article/details/85038731