本题的大意是,人类的基因组成包括4种碱基:A,C,G,T构成,现在要根据相应的矩阵分析给出的两个DNA的相似度。在计算的过程中,由于两个DNA长度可能不等,需要插入“-”来填补,需要解决的问题就是如何插入“-”使得两个DNA的相似度最高。
做到这题时,正好在编程之美上看到了一题类似的题,根据对那题的理解马上勾勒出了程序的大体框架:假设两个DNA分别为A,B。对于每个碱基,都有三种情况:在A中插入“-”,在B中插入“-”,以及A,B中均不插入。根据这样的分析,可以定义一个状态:d(i,j),表示的是A中处理位置为i,B中处理位置为j能取得的最大相似度。不难求出三种情况下的状态转移方程。我用的是递归方法解决,需要注意一下边界问题,同时需要注意的是初始化不能初始化为-1,因为在计算过程中,有的相似度会是负数。
#include <stdio.h>
#include <string.h>
int scores[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,-10
};
char A_query[102];
char B_query[102];
int Alen,Blen;
int d[102][102];
int max(int a,int b,int c);
int getscore(char a);
int main()
{
int count,i,j;
//freopen("test.txt","r",stdin);
scanf("%d",&count);
while(count--)
{
scanf("%d",&Alen);
getchar();
scanf("%s",A_query);
scanf("%d",&Blen);
getchar();
scanf("%s",B_query);
for(i=0;i<102;i++)
for(j=0;j<102;j++)
d[i][j]=-10000;
printf("%d\n",search(0,0));
}
return 0;
}
int search(int A_index,int B_index)
{
int len1,len2,len3;
int total,i;
total=0;
if(d[A_index][B_index]>-10000)
return d[A_index][B_index];
if(A_index>=Alen) //边界处理:某一DNA已到最后一个元素时,只能在后面添加"-"
{
for(i=B_index;i<Blen;i++)
total+=scores[4][getscore(B_query[i])];
return total;
}
if(B_index>=Blen)
{
for(i=A_index;i<Alen;i++)
total+=scores[getscore(A_query[i])][4];
return total;
}
len1=search(A_index+1,B_index)+scores[getscore(A_query[A_index])][4];
len2=search(A_index+1,B_index+1)+scores[getscore(A_query[A_index])][getscore(B_query[B_index])];
len3=search(A_index,B_index+1)+scores[4][getscore(B_query[B_index])];
total=max(len1,len2,len3);
d[A_index][B_index]=total;
return d[A_index][B_index];
}
int getscore(char a)
{
switch(a)
{
case 'A':return 0;
case 'C':return 1;
case 'G':return 2;
case 'T':return 3;
case '-':return 4;
default:break;
}
return -1;
}
int max(int a,int b,int c)
{
int temp;
temp=a>b?a:b;
return temp>c?temp:c;
}