题目来源:POJ 1080 Human Gene Functions

http://acm.pku.edu.cn/JudgeOnline/problem?id=1080

解法类型:动态规划

解题思路:

         网上一份解题报告:写的很详细,就此摘来:

http://nash250.blog.hexun.com/9794371_d.html

和《算法导论》中动态规划章节的LCS(Longest common subsequence 最长公共子序列)所用例子基本是一样的,都是测两串基因的相似程度,不同之处在于《导论》用LCS表示两基因的相似程度,LCS越长,相似度越大。本题中用下面的核苷相近程度取值表表示两基因相似程度,各相应核苷对匹配值之和越高,相似程度自然越大。

首先回想LCS的解法,

设两基因串为an,bm

a[i],b[j]分别表示a串的第i个核苷

b串的第j个核苷

ax,by为an,bm的子串;

c[x][y]表示子串ax,by间最长子序列的长度

则c[n][m]表示串an,bm间最长子序列的长度

则有如下的状态转移方程:

c[i][j]=c[i-1][j-1]+1                            if i,j>0 a[i]=b[j]

c[i][j]=max(c[i][j-1],c[i-1][j])              if i,j>0 a[i]≠[j]

再思考该动规方程的边界条件:

for i=0 to n do c[i, 0] ← 0

for j=0 to n do c[0, j] ← 0

即每个子序列与长度为0的串的最长子序列的长度为0

此即为LCS的解法

针对本题,对LCS的状态方程稍作修改,

设两基因串为an,bm

a[i],b[j]分别表示a串的第i个核苷

b串的第j个核苷

ax,by为an,bm的子串;

c[x][y]表示子串ax,by间最大相似程度值

则c[n][m]表示串an,bm间最大相似程度值

value(x,y)表示核苷x核苷y的相似程度值

'-'表示核苷为空

则有如下的状态转移方程:

c[i][j]=max(c[i-1][j-1]+value(a[i],b[j]),c[i][j-1]+value('-',b[j]),c[i-1][j]+value(a[i],'-'))

if i,j>0 a[i]≠[j]

再思考该动规方程的边界条件:

for i=0 to n do c[i][0] ← 0

for j=0 to n do c[0][j] ← 0

即每个子序列与空串之间的相似程度值的和为0

至此本题的思路已经清晰

注意:

         考虑清楚临界情况。

源程序:

#include <iostream>



using namespace std;



long a[110],b[110],v[110][110];

long r[][5]={0,-3,-4,-2,-1,-3,5,-1,-2,-1,-4,-1,5,-3,-2,-2,-2,-3,5,-2,-1,-1,-2,-2,5};



long change(char c)

{

switch (c)

{

case'A': return 1;

case'C': return 2;

case'G': return 3;

case'T': return 4;

}

}



int main()

{

long caseNum,aLen,bLen,i,j,tmp,all,aOnly,bOnly;

char c;

cin
>>caseNum;

while(caseNum--)

{

cin
>>aLen;

for(i=1;i<=aLen;i++)

{

cin
>>c;

a[i]
=change(c);

}

cin
>>bLen;

for(i=1;i<=bLen;i++)

{

cin
>>c;

b[i]
=change(c);

}

v[
0][0]=0;

for(i=1;i<=aLen;i++) v[i][0]=r[a[i]][0]+v[i-1][0];

for(i=1;i<=bLen;i++) v[0][i]=r[0][b[i]]+v[0][i-1];

//临界情况是当前这个点和 "-" 得到的值,

//与前面累加得到的,而不仅仅是当前点得到的值



for(i=1;i<=aLen;i++)

for(j=1;j<=bLen;j++)

{

all
=v[i-1][j-1]+r[a[i]][b[j]];

aOnly
=v[i-1][j]+r[a[i]][0];

bOnly
=v[i][j-1]+r[0][b[j]];

tmp
=aOnly>bOnly?aOnly:bOnly;

v[i][j]
=all>tmp?all:tmp;

}

cout
<<v[aLen][bLen]<<endl;

}

return 0;

}
posted on 2011-05-11 17:35  geeker  阅读(558)  评论(0编辑  收藏  举报