题意:有一个基因配对表,基因序列任意位置可插入空位‘-’使两段基因序列相等,求按最佳方案
插入空位后得到的 两段基因序列的最大匹配值。
分析:类似于最长公共子序列。
dp方程:dp[i][j]=max(dp[i-1][j-1]+solve(s1[i],s2[j]),dp[i-1][j]+solve(s1[i],'-'),dp[i][j-1]+solve('-',s2[j])
dp[i][j]表示s1串中i长度的序列和s2串中j长度的序列的最佳匹配值。
初始化条件 dp[i][0]=dp[i-1][0]+solve(s1[i],‘-’),dp[0][j]=dp[0][j-1]+solve(‘-’,s2[j])。
s1[i]可以对应s2[j]或者‘-’,同理,s2[j]也可以对应s1[i]和‘-’。初始化条件是根据这个推到的。
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int dp[110][110];
char s1[105],s2[105];
int max(int x,int y)
{
return x>y?x:y;
}
int table[6][6]=
{
0,0,0,0,0,0,
0,5,-1,-2,-1,-3,
0,-1,5,-3,-2,-4,
0,-2,-3,5,-2,-2,
0,-1,-2,-2,5,-1,
0,-3,-4,-2,-1,-1000000
};
int getidex(char a)
{
if(a=='A') return 1;
else if(a=='C') return 2;
else if(a=='G') return 3;
else if(a=='T') return 4;
else return 5;
}
int solve(char x,char y)
{
int xx=getidex(x);
int yy=getidex(y);
return table[xx][yy];
}
int main()
{
int T,len1,len2;
scanf("%d",&T);
while(T--)
{
scanf("%d %s",&len1,s1+1);
scanf("%d %s",&len2,s2+1);
memset(dp,0,sizeof(dp));
for(int i=1;i<=len1;i++)
dp[i][0]=dp[i-1][0]+solve(s1[i],'-');
for(int i=1;i<=len2;i++)
dp[0][i]=dp[0][i-1]+solve('-',s2[i]);
for(int i=1;i<=len1;i++)
{
for(int j=1;j<=len2;j++)
{
dp[i][j]=max(dp[i-1][j-1]+solve(s1[i],s2[j]),dp[i-1][j]+solve(s1[i],'-'));
dp[i][j]=max(dp[i][j],dp[i][j-1]+solve('-',s2[j]));
}
}
printf("%d\n",dp[len1][len2]);
}
return 0;
}