给出两个序列,可以任意往他们之间插入‘-’, 求等长度后,按照给出的表计算得到的sum
可知,尽可能让相同的字母对齐才会得到最优的sum,
也就是看他们有多少字母相同,类似LCS
dp方程类似LCS:
if(a[i]==b[j])
dp[i][j]=dp[i-1][j-1]+get(i,j); //相等的情况就是让他们2个对齐
else //否则就看是否要插入‘-’,以及插入在上面还是在下面
dp[i][j]=max(dp[i-1][j-1]+get(i,j),dp[i-1][j]+get(i,'-'),dp[i][j-1]+get('-',j));
要注意的问题就是 【边界的初始化】;
#include <cmath>
#include <cstdio>
#include <cstring>
#include <limits>
#include <string>
#include <iostream>
#include <list>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;
const int inf=2147483647;
int min(int a,int b){return a<b?a:b;}
int min(int a,int b,int c){return min(min(a,b),c);}
int max(int a,int b){return a>b?a:b;}
int max(int a,int b ,int c){return max(max(a,b),c);}
char tm[200];
char nm[200];
char *a,*b;
int get(int j,char aa)
{
if (a[j]=='A') return -3;
if (a[j]=='C') return -4;
if (a[j]=='G') return -2;
if (a[j]=='T') return -1;
return 0;
}
int get(char aa,int j)
{
if (b[j]=='A') return -3;
if (b[j]=='C') return -4;
if (b[j]=='G') return -2;
if (b[j]=='T') return -1;
return 0;
}
int get(int i,int j)
{
if (a[i]=='A')
{
if (b[j]=='A') return 5;
if (b[j]=='C') return -1;
if (b[j]=='G') return -2;
if (b[j]=='T') return -1;
if (b[j]=='-') return -3;
}
if (a[i]=='C')
{
if (b[j]=='A') return -1;
if (b[j]=='C') return 5;
if (b[j]=='G') return -3;
if (b[j]=='T') return -2;
if (b[j]=='-') return -4;
}
if (a[i]=='G')
{
if (b[j]=='A') return -2;
if (b[j]=='C') return -3;
if (b[j]=='G') return 5;
if (b[j]=='T') return -2;
if (b[j]=='-') return -2;
}
if (a[i]=='T')
{
if (b[j]=='A') return -1;
if (b[j]=='C') return -2;
if (b[j]=='G') return -2;
if (b[j]=='T') return 5;
if (b[j]=='-') return -1;
}
if (a[i]=='-')
{
if (b[j]=='A') return -3;
if (b[j]=='C') return -4;
if (b[j]=='G') return -2;
if (b[j]=='T') return -1;
}
}
int dp[205][205];
int main()
{
int t;
cin>>t;
while(t--)
{
int i,j,k,h;
int n,m;
memset(dp,0,sizeof(dp));
cin>>n;getchar();
for (i=1;i<=n;i++)
scanf("%c",&tm[i]);
cin>>m;getchar();
for (i=1;i<=m;i++)
scanf("%c",&nm[i]);
if (n<m) //统一规定上面的序列为较长的
{
swap(n,m);
a=nm;
b=tm;
}
else
{
a=tm;
b=nm;
}
for(i=1;i<=n;i++)
dp[i][0]=dp[i-1][0]+get(i,'-'); //当j=1时,在判断dp[i][j-1]时,表示i与j-1对齐,而在第一个序列插入‘-’与第二个序列的j对齐,
//因为j-1已经为0了,所以意味着在前面插入了 i个'-',所以需要在这里初始化好边界条件,否则有问题.
for (i=1;i<=m;i++)
dp[0][i]=dp[0][i-1]+get('-',i);
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
if(a[i]==b[j])
dp[i][j]=dp[i-1][j-1]+get(i,j); //相等的情况就是让他们2个对齐
else //否则就看是否要插入‘-’,以及插入在上面还是在下面
dp[i][j]=max(dp[i-1][j-1]+get(i,j),dp[i-1][j]+get(i,'-'),dp[i][j-1]+get('-',j));
}
}
printf("%d\n",dp[n][m]);
}
return 0;
}