题目描述
大家都知道,基因可以看作一个碱基对序列。它包含了 4 种核苷酸,简记作 A,C,G,T 。生物学家正致力于寻找人类基因的功能,以利用于诊断疾病和发明药物。
在一个人类基因工作组的任务中,生物学家研究的是:两个基因的相似程度。因为这个研究对疾病的治疗有着非同寻常的作用。
题目描述
两个基因的相似度的计算方法如下:
对于两个已知基因,例如 AGTGATG 和 GTTAG ,将它们的碱基互相对应。当然,中间可以加入一些空碱基 -,例如:
这样,两个基因之间的相似度就可以用碱基之间相似度的总和来描述,碱基之间的相似度如下表所示:
那么相似度就是: (-3)+5+5+(-2)+(-3)+5+(-3)+5=9 。因为两个基因的对应方法不唯一,例如又有:
相似度为: (-3)+5+5+(-2)+5+(-1)+5=14 。规定两个基因的相似度为所有对应方法中,相似度最大的那个。
输入输出格式
输入格式:
共两行。每行首先是一个整数,表示基因的长度;隔一个空格后是一个基因序列,序列中只含 A,C,G,T 四个字母。 1 ≤ 序列的长度 ≤100 。
输出格式:
仅一行,即输入基因的相似度。
输入输出样例
输入样例#1:
7 AGTGATG
5 GTTAG输出样例#1:
14
源代码
#include<iostream>
#include<string>
using namespace std;
int max(int x,int y)
{
if(x>y)
return x;
else
return y;
}
int main()
{
int calculate[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 a,b;//基因长度
string gene_a,gene_b;//基因序列
int num_a[110],num_b[110];//用于将基因序列转为编码存储的数组
int dp[110][110]={0};//初始化
int i,j;
cin>>a>>gene_a;//基因序列a
cin>>b>>gene_b;//基因序列b
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
dp[i][j]=-1e8; //初始化为一极小值
for(i=1;i<=a;i++)//将基因序列a转为题设所给相似度表格中的数字代码
{
if(gene_a[i-1]=='A') num_a[i]=0;
if(gene_a[i-1]=='C') num_a[i]=1;
if(gene_a[i-1]=='G') num_a[i]=2;
if(gene_a[i-1]=='T') num_a[i]=3;
}
for(i=1;i<=b;i++)//将基因序列b转为题设所给相似度表格中的数字代码
{
if(gene_b[i-1]=='A') num_b[i]=0;
if(gene_b[i-1]=='C') num_b[i]=1;
if(gene_b[i-1]=='G') num_b[i]=2;
if(gene_b[i-1]=='T') num_b[i]=3;
}
/*
特判情况
第一个基因第1个与第二个基因第0个匹配时,与空碱基匹配的值相同,可视为与空碱基匹配
同理,第二个基因第1个与第一个基因第0个匹配时,与空碱基匹配的值相同
*/
for(i=1;i<=a;i++) dp[i][0]=dp[i-1][0]+calculate[num_a[i]][4];
for(i=1;i<=b;i++) dp[0][i]=dp[0][i-1]+calculate[num_b[i]][4];
/*
比较碱基对相似度,共三种情况:
①不插入空碱基,直接进行配对
②序列a不变,在序列b中插入空碱基
③序列b不变,在序列a中插入空碱基
*/
for(i=1;i<=a;i++)
{
for(j=1;j<=b;j++)
{
dp[i][j]=max( dp[i][j] , dp[i][j-1]+calculate[ num_b[j] ][4] );//序列a中插空碱基
dp[i][j]=max( dp[i][j] , dp[i-1][j]+calculate[ num_a[i] ][4] );//序列b中插空碱基
dp[i][j]=max( dp[i][j] , dp[i-1][j-1]+calculate[ num_a[i] ][ num_b[j] ] );//不插入直接配对
}
}
cout<<dp[a][b];
return 0;
}