/**观察题目给出的一个最优解:AGTGATG-GTTA-G将其从某一处切开,如果左边部分的分值不是最大,那么将其进行调整,使其分值变大,则整个解分值变大,与已知的最优矛盾。所以左边部分的分值必是最大。同理,右边也是。可见满足最优子结构的性质。考虑使用DP:设两个DNA序列分别为s1,s2,长度分别为len1,len2,score为分值表。f[i,j]表示子串s1[1..i]和s2[1..j]的分值。考虑一个f[i,j],我们有:1.s1取第i个字母,s2取“-”:f[i-1,j] + score[s1[i],'-']2.s1取“-”,s2取第j个字母:f[i,j-1] + score['-',s2[j]]3.s1取第i个字母,s2取第j个字母:f[i-1,j-1] + score[s1[i],s2[j]]即f[i,j] = max(f[i-1,j] + score[s1[i],'-'], f[i,j-1] + score['-', s2[j]], f[i-1,j-1] + score[s1[i],s2[j]]);然后考虑边界条件,这道题为i或j为0的情况。当i=j=0时,即为f[0,0],这是在计算f[1,1]时用到的,根据f[1,1] = f[0,0] + score[s1[i], s2[j]],明显有f[0,0] = 0。当i=0时,即为f[0,1..len2],有了f[0,0],可以用f[0,j] = f[0,j-1] + table['-',s2[j]]来计算。当j=0时,即为f[1..len1,0],有了f[0,0],可以用f[i,0] = f[i-1,0] + table[s1[i],'-']来计算。至于计算顺序,只要保证计算f[i,j]的时候,使用到的f[i-1,j],f[i,j-1],f[i-1,j-1]都计算出来了就行了。所谓划分阶段也就是为了达到这个目的。这样我们使用一个二重循环就可以了。*//**以 AGTGATG 和 GTTAG 为例 A G T G A T G 0 2 3 2 0 3 2 G T T A G 2 3 3 0 2 0 1 2 3 4 5 ------------------------------------------------- - -- --- ---- ----- G GT GTT GTTA GTTAG 0 0 -2 -3 -4 -7 -9 ------------------------------------------------- A A -A --A ---A ---A- - G GT GTT GTTA GTTAG 1 -3 -2 -3 -4 1 -1 ------------------------------------------------- AG AG AG- AG-- ---A- ---AG -- -G -GT -GTT GTTAG GTTAG 2 -5 2 1 0 -1 6 ------------------------------------------------- AGT AGT AGT AGT- AGT-- ---AGT --- -G- -GT -GTT -GTTA GTTAG- 3 -6 1 7 6 3 5 ------------------------------------------------- AGTG AGTG AGTG AGTG AGT-G AGT--G ---- -G-T -GT- -GTT -GTTA -GTTAG 4 -8 -1 5 5 4 8 ------------------------------------------------- AGTGA AGTGA AGTGA AGTGA AGTGA AGTGA- ----- -G-T- -GT-- -GT-T -GTTA -GTTAG 5 -11 -4 2 4 10 8 ------------------------------------------------- AGTGAT AGTGAT AGTGAT AGTGAT AGTGAT AGTGAT ------ -G-T-- -G-T-T -GT--T -GTTA- -GTTAG 6 -12 -5 1 7 9 8 ------------------------------------------------- AGTGATG AGTGATG AGTGATG AGTGATG AGTGATG AGTGATG ------- ------G -G-T-T- -GT--T- -GTTA-- -GTTA-G 7 -14 -7 -1 5 7 14 -------------------------------------------------*/#include<stdio.h>void change(char s[],int d[],int len){ int i; for(i=0;i<len;i++){ if(s[i]=='A')d[i]=0; else if(s[i]=='C')d[i]=1; else if(s[i]=='G')d[i]=2; else if(s[i]=='T')d[i]=3; }}int max(int a,int b,int c){ int i; i=a>b?a:b; return i>c?i:c;}int main(){ int score[5][5]={ 5,-1,-2,-1,-3, -1, 5,-3,-2,-4, -2,-3, 5,-2,-2, -1,-2,-2, 5,-1, -3,-4,-2,-1, 0}; int f[201][201],d1[101],d2[101]; int test,len1,len2,i,j; char s1[101],s2[101]; int a,b,c; //freopen("in.txt","r",stdin); scanf("%d",&test); while(test--){ scanf("%d%s",&len1,s1); change(s1,d1,len1); scanf("%d%s",&len2,s2); change(s2,d2,len2); for(i=0;i<=len1;i++){ for(j=0;j<=len2;j++){ if(i==0&&j){ f[0][j]=f[0][j-1]+score[4][d2[j-1]]; } else if(i==0&&j==0){ f[0][0]=0; } else if(i&&j==0){ f[i][0]=f[i-1][0]+score[d1[i-1]][4]; } else{ a=f[i-1][j]+score[d1[i-1]][4]; b=f[i][j-1]+score[4][d2[j-1]]; c=f[i-1][j-1]+score[d1[i-1]][d2[j-1]]; f[i][j]=max(a,b,c); } } } printf("%d\n",f[len1][len2]); }}