动态规划,其实这题并不难,大概是我dp题做的不够,才没想出动态转移方程,看了discuss里的题解,唉~今后仍需努力啊
f[i,j]表示子串s1[1..i]和s2[1..j]的分值。考虑一个f[i,j],我们有:
1.s1取第i个字母,s2取“-”:f[i-1,j] + score[s1,'-']
2.s1取“-”,s2取第j个字母:f[i,j-1] + score['-',s2[j]]
3.s1取第i个字母,s2取第j个字母:f[i-1,j-1] + score[s1,s2[j]]
即f[i,j] = max(f[i-1,j] + score[s1,'-'], f[i,j-1] + score['-',s2[j]], f[i-1,j-1] + score[s1,s2[j]]);
然后考虑边界条件,这道题为i或j为0的情况。
当i=j=0时,即为f[0,0],这是在计算f[1,1]时用到的,根据f[1,1] = f[0,0] + score[s1, 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,'-']来计算。
program poj1080;
const
v:array['1'..'5','1'..'5'] of integer=((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));
var
f:array[0..100,0..100] of integer;
s1,s2,ss:string;
l1,l2,i,j,k,n:integer;
procedure change(var l:integer;var s:string);
var
p,c,i:integer;
begin
p:=pos(' ',ss);
val(copy(ss,1,p-1),l,c);
while ss[p]=' ' do inc(p);
s:=copy(ss,p,l);
for i:=1 to l do
case s[i] of
'A':s[i]:='1';
'C':s[i]:='2';
'G':s[i]:='3';
'T':s[i]:='4';
'-':s[i]:='5';
end;
end;
function max(p,q:integer):integer;
begin
if p>q then max:=p
else max:=q;
end;
begin
readln(n);
for k:=1 to n do
begin
fillchar(f,sizeof(f),0);
readln(ss);
change(l1,s1);
readln(ss);
change(l2,s2);
f[0,0]:=0;
for i:=1 to l1 do
f[i,0]:=f[i-1,0]+v['5',s1[i]];
for i:=1 to l2 do
f[0,i]:=f[0,i-1]+v[s2[i],'5'];
for i:=1 to l1 do
for j:=1 to l2 do
f[i,j]:=max(f[i-1,j-1]+v[s1[i],s2[j]],max(f[i,j-1]+v['5',s2[j]],f[i-1,j]+v[s1[i],'5']));
writeln(f[l1,l2]);
end;
end.