【动态规划】【poj 1080】Human Gene Functions
问题
给定你两个基因序列,每个序列中只包含’AGCT’四种字符,长度不一定相等,每个序列都可以在任意位置添上‘-’使之边长,最后使两个序列变成等长,之后相应位置上的字符相互对应可以得到一个分数,现在给出不同的对应得到的分数,规定不使'-’对应。
让你求出能够得到的最大的分数。
分析
很像lcs问题,可以根据lcs写出这样的方程:f[i,j]:=max{f[i-1,j-1]+match(s1[i],s2[j]),f[i-1,j]+match(s1[i],’-’),f[i,j-1]+match(‘-’,s2[j])};
怎样来考虑这个问题呢?
现在第一个字符串的前i位和第二个串的前j位的最值,之和当前这一位是否选取有关。如果选取不会对之前已产生的最值产生任何影响所以是f[i-1,j-1]+match(s1[i],s2[j])。
剩下的情况要仔细考虑方程的含义,由于两个位置如果能够得分必须通过增添一定的字符使这两个串等长,也就是说i,j位的字符在变换后的字符串中一定是在相对应的位置。如果让i-1位和j位得到一个分数(f[i-1,j])那么第i位必然对应一个’-‘,这样不会影响之前的状态,也就是没有后效性。
所以就有f[i-1,j]+match(s1[i],’-’),第三个状态同理。
为了使方程满足其含义,初始化很关键f[0,i]:=f[0,i-1]+match(‘-’,s2[i]),如果让当前位对应,之前的就需要添加一定的字符,也就是说我们在一开始的初始化就满足了方程的含义,这一点很关键!特别注意,是累加,因为是求总的分数,加多少‘-’就多多少值。
code
program liukeke;
var
f:array[0..105,0..105] of longint;
s1,s2:string;
match:array[1..5,1..5] of longint=((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));
ss:array['-'..'T'] of longint;
n,zu,w,i,j:longint;
function min(a,b,c):longint;
begin
min:=a;
if b<min then min:=b;
if c<min then min:=c;
end;
begin
ss['A']:=1;ss['C']:=2;ss['G']:=3;ss['T']:=4;ss['-']:=5;
readln(n);
for zu:=1 to n do
begin
fillchar(f,sizeof(f),127);
readln(s1);
readln(s2);
w:=pos(' ',s1);
delete(s1,1,w);
w:=pos(' ',s2);
delete(s2,1,w);
for i:=1 to length(s2) do
f[0,i]:=match[ss['-'],ss[s2[i]]];
for i:=1 to length(s1) do
f[i,0]:=match[ss[s1[i]],ss['-']];
for i:=1 to length(s1) do
for j:=1 to length(s2) do
f[i,j]:=min(f[i-1,j-1]+match[ss[s1[i]],ss[s2[j]]],s[i-1,j]+match[ss[s1[i]],ss['-']],s[i,j-1]+match[ss['-'],ss[s2[i]]]);
writeln(f[length(s1),length(s2)]);
end;
end.
反思
经典问题的变形,只是提供思路,方程的具体含义发生了变化,体现了动态规划中边界条件的重要性。
浙公网安备 33010602011771号