此题与LCS非常相似。

因为是两个串的比对,所以我们很容易想到用f【i】【j】来表示a串的前i个碱基和b串的前j个碱基配出的最大相似度(每一个碱基都配对一个碱基,或者配空碱基),

那么这个状态的前驱就有三种:

①f【i】【j-1】+(b【j】与空碱基的相似度)

②f【i-1】【j】+(a【i】与空碱基的相似度)

③f【i-1】【j-1】+a【i】与b【j】的相似度

那么怎么表示相似度呢,用函数吗,当然是数组更方便

int mat[5][5]={{-1000,-3,-4,-2,-1},{-3,5,-1,-2,-1},{-4,-1,5,-3,-2},{-2,-2,-3,5,-2},{-1,-1,-2,-2,5}};(可以把读入的字符换成整数存起来)

完整代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=105;
int n,m;
char s1[N],s2[N],t;
int mat[5][5]={{-1000,-3,-4,-2,-1},{-3,5,-1,-2,-1},{-4,-1,5,-3,-2},{-2,-2,-3,5,-2},{-1,-1,-2,-2,5}};
int a[N],b[N],f[N][N];//0-0,1 2 3 4        1-0,1,2,3,4
void init();
int main()
{
	//freopen("in.txt","r",stdin);
	init();
	memset(f,0x8f,sizeof(f));
	f[0][0]=0;
	for(int i=0;i<=n;i++)
	   for(int j=0;j<=m;j++)
	    {
	    	int x1=mat[0][b[j]];
	    	int x2=mat[a[i]][0];
	    	int x3=mat[a[i]][b[j]];
	    	/*if(i==2&&j==1){
	    		cout<<f[i-1][j-1]<<" "<<a[i]<<" "<<b[j]<<endl;
			}*/
	    	if(i&&j) f[i][j]=max(f[i][j],f[i-1][j-1]+x3);
	    	if(i) f[i][j]=max(f[i][j],f[i-1][j]+x2);
	    	if(j) f[i][j]=max(f[i][j],f[i][j-1]+x1);
		}
	cout<<f[n][m]<<endl;
	return 0;
}
void init()
{
	cin>>n>>s1>>m>>s2;
    for(int i=0;i<n;i++)
    {
    	switch (s1[i])
    	{
    		case 'A':a[i+1]=1;break;
    		case 'C':a[i+1]=2;break;
    		case 'G':a[i+1]=3;break;
    		case 'T':a[i+1]=4;break;
    		default :break;
		}
	}
	for(int i=0;i<m;i++)
    {
    	switch (s2[i])
    	{
    		case 'A':b[i+1]=1;break;
    		case 'C':b[i+1]=2;break;
    		case 'G':b[i+1]=3;break;
    		case 'T':b[i+1]=4;break;
    		default :break;
		}
	}
}

  

 

01-02 17:45