题意:计算两个DNA碱基序列的相似度,可以插入空格来匹配任一个碱基,题目中给了任意匹配的代价。
思路:score[i][j]为下列 三者的最大值:seq1[i]与seq2[j]匹配 + score[i-1][j-1];空格与seq1[i]匹配 + score[i-1][j];空格与seq2[j]匹配 + score[i][j-1]。
初值,score,第一列表示一直用空格匹配第一个序列,第一行表示一直用空格匹配第二个序列。
代码中的map可以用一个函数代替,我没用过,所以用它试试的。
#include<cstdio>
#include<map>
using namespace std;
int cost[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}};
map<char, int> m;
int score[104][104];//DP空间
char seq1[104], seq2[104]; //从1开始
int len1, len2;
void match(){
score[0][0] = 0;
for(int i=1; i<=len1; ++i)
score[i][0] = score[i-1][0] + cost[m[seq1[i]]][4];
for(int j=1; j<=len2; ++j)
score[0][j] = score[0][j-1] + cost[m[seq2[j]]][4];
for(int i=1; i<=len1; ++i)
for(int j=1; j<=len2; ++j){
int max, tmp;
max = score[i-1][j-1] + cost[m[seq1[i]]][m[seq2[j]]];
tmp = score[i-1][j] + cost[m[seq1[i]]][4];
if(tmp > max)
max = tmp;
tmp = score[i][j-1] + cost[m[seq2[j]]][4];
if(tmp > max)
max = tmp;
score[i][j] = max;
}
}
int main(){
// freopen("in", "r", stdin);
m['A'] = 0;
m['C'] = 1;
m['G'] = 2;
m['T'] = 3;
m['-'] = 4;
int cases;
scanf("%d", &cases);
while(cases--){
scanf("%d %s", &len1, &seq1[1]);
scanf("%d %s", &len2, &seq2[1]);
match();
printf("%d\n", score[len1][len2]);
}
return 0;
}