您的位置:首页 > 其它

ZOJ1027

2016-02-19 18:16 337 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=27

类似于最长公共子序列。

用f[i][j]表示第一个基因序列s1的前i个字符和第二个基因序列s2的前j个字符对齐后的最大相似度,函数dis用来计算两个字符之间的相似度,分三种情况:

1.在s1的第i个字符后面插入空格与s2的第j个字符匹配,f[i][j] = f[i][j-1]+dis(s2[j],'-');

2.在s2的第j个字符后面插入空格与s1的第j个字符匹配,f[i][j] = f[i-1][j]+dis(s1[i],'-');

3.让s1的第i个字符与s2的第j个字符匹配,f[i][j] = f[i-1][j-1]+dis(s1[i],s2[j])。

注意考虑初始化:

for (int i=1; i<=n; i++)

f[i][0] = f[i-1][0] + dis(s1[i],'-');

for (int j=1; j<=m; j++)

f[0][j] = f[0][j-1] + dis(s2[j],'-');

#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;

int f[110][110];
int d[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,-100}};

int dis(char c1, char c2)
{
int a, b;
switch (c1)
{
case 'A':a = 0; break;
case 'C':a = 1; break;
case 'G':a = 2; break;
case 'T':a = 3; break;
case '-':a = 4; break;
}
switch (c2)
{
case 'A':b = 0; break;
case 'C':b = 1; break;
case 'G':b = 2; break;
case 'T':b = 3; break;
case '-':b = 4; break;
}
return d[a][b];
}

int main()
{
int T;

scanf("%d",&T);
while (T--)
{
int n,m;
char s1[110],s2[110];
scanf("%d%s",&n,&s1[1]);
scanf("%d%s",&m,&s2[1]);
memset(f,0,sizeof(0));
for (int i=1; i<=n; i++)
f[i][0] = f[i-1][0] + dis(s1[i],'-');
for (int j=1; j<=m; j++)
f[0][j] = f[0][j-1] + dis(s2[j],'-');
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
{
f[i][j] = max(max(f[i][j-1]+dis(s2[j],'-'),
f[i-1][j]+dis(s1[i],'-')),
f[i-1][j-1]+dis(s1[i],s2[j]));
}
cout<<f
[m]<<endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: