题目大意:
太长的英语,我就直接读了测试样例和题目中一些可以看的。。。。好像是关于什么人类基因工程什么的,
腺嘌呤脱氧核糖核苷酸~
每组测试实例给你两串由AGCT四个字母组成的字符串(每个字符串100字符)。
有一个得分表:
分析:
说出来你们可能不相信,这个题我还没想很明白就应开始写了,然后居然写出来了。当时就是还没怎么仔细想好细节,就想,我要知道这个,就只要知道另外的几个其他的状态就好了,并没有很清楚的想明白初始条件,以及这么递归下去会递归到什么样子。
dp建立:
dp [ i ] [ j ]表示第一行前 i 个字符和第二行前 j 个字符进行匹配最多可以获得多少的得分。
递推方程:
dp [ i ] [ j ]=max { dp [ x-1 ] [ y ] + move [ a[x] ] [ 5 ] , dp [ x ] [ y-1 ] + move [ 5 ] [ b[y] ] , dp [ x-1 ] [ y-1 ] + move [ a[x] ] [ b[y] ] }
这次用的是递归,不是递推。然后为了防止重复计算,使用 best [ ] [ ] 数组记录每次递归下来的结果。类似于记忆化搜索吧。
#include<iostream>
#include<string.h>
#include<stdio.h>
#define inf 0x3f3f3f3f
using namespace std;
int n;
//int dp[150][150]={0};
int a[150]={0};
int b[150]={0};
int move[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,-inf};
int best[150][150]={0};
void input()
{
cin>>a[0];
getchar();
for(int i=1;i<=a[0];i++)
{
char l;
scanf("%c",&l);
if(l=='A')a[i]=1;
if(l=='C')a[i]=2;
if(l=='G')a[i]=3;
if(l=='T')a[i]=4;
}
cin>>b[0];
getchar();
for(int i=1;i<=b[0];i++)
{
char l;
scanf("%c",&l);
if(l=='A')b[i]=1;
if(l=='C')b[i]=2;
if(l=='G')b[i]=3;
if(l=='T')b[i]=4;
}
}
int my_max(int aa,int bb,int cc)
{
int t=aa;
if(t<bb)t=bb;
if(t<cc)t=cc;
return t;
}
int dp(int x,int y)
{
if(x==0&&y==0)return 0;
if(best[x][y]!=0)return best[x][y];
/*if(a[x]==b[y]) { best[x][y]=dp(x-1,y-1)+5; return best[x][y]; }*/
best[x][y]=my_max(dp(x-1,y)+move[a[x]][5],dp(x,y-1)+move[5][b[y]],dp(x-1,y-1)+move[a[x]][b[y]]);
return best[x][y];
}
void init()
{
for(int i=1;i<=a[0];i++)
{
best[i][0]=best[i-1][0]+move[a[i]][5];
}
for(int i=1;i<=b[0];i++)
{
best[0][i]=best[0][i-1]+move[5][b[i]];
}
}
int main()
{
int test;
cin>>test;
while(test--)
{
input();
//cout<<a[0]<<b[0];
init();
cout<<dp(a[0],b[0])<<endl;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(best,0,sizeof(best));
}
}