https://www.luogu.org/problemnew/show/P1140
根据题目给出的碱基配对表,发现:
1.两基因相同时产生+5,其余都是负数。
2.任意两个不同基因相配,直接配要好于分别与空碱基配。但是两基因不满足上1点的长度不同,所以必须有一些基因与空碱基相配。
设f(i,j)表示第一个基因前i个和第二个基因前j个相配的最大相似度
边界为f(0,j)=第二个基因前j个分别与空基因相配的相似度
f(i,0)=第一个基因前i个分别与空基因相配的相似度
f(i,j)= f(i-1,j-1)+5 ,a[i]==b[j]
max( f(i-1,j)+a[i]配空 ,f(i,j-1)+b[j]配空 ,f(i-1,j-1)+a[i]配b[j] ) ,a[i]!=b[j]
#include<bits/stdc++.h>
using namespace std;
int n,m,d[105][105];
char a[105],b[105];
map<char,int>score;
int score2[300][300];
void init()
{
score['T']=-1;
score['G']=-2;
score['A']=-3;
score['C']=-4;
score2['A']['C']=-1;
score2['A']['T']=-1;
score2['A']['G']=-2;
score2['T']['C']=-2;
score2['T']['G']=-2;
score2['C']['G']=-3;
}
int main()
{
freopen("input.in","r",stdin);
scanf("%d%s%d%s",&n,a+1,&m,b+1);
init();
int sum=0;
for(int j=1;j<=m;j++)
{
sum+=score[b[j]];
d[0][j]=sum;
}
sum=0;
for(int j=1;j<=n;j++)
{
sum+=score[a[j]];
d[j][0]=sum;
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(a[i]==b[j])d[i][j]=d[i-1][j-1]+5;
else d[i][j]=max(d[i-1][j-1]+min(score2[a[i]][b[j]],score2[b[j]][a[i]]),max(d[i-1][j]+score[a[i]],d[i][j-1]+score[b[j]]));
}
}
cout<<d[n][m]<<endl;
return 0;
}