DP专练(1):align

http://hi.baidu.com/raulliubo/blog/item/5538f1f88931860bd9f9fd9b.html

 

顺序对齐

源程序名   ALIGN.??? (PAS,C,CPP)

可执行文件名   ALIGN.EXE

输入文件名   ALIGN.IN

输出文件名     ALIGN.OUT

考虑两个字符串右对齐的最佳解法。例如,有一个右对齐方案中字符串是AADDEFGGHC和ADCDEGH。

AAD_DEFGGHC

ADCDE__GH_

每一个数值匹配的位置值2分,一段连续的空格值-1分。所以总分是匹配点的2倍减去连续空格的段数,在上述给定的例子中,6个位置(A,D,D,E,G,H)匹配,三段空格,所以得分2*6+(-1)*3=9,注意,我们并不处罚左边的不匹配位置。若匹配的位置是两个不同的字符,则既不得分也不失分。

请你写个程序找出最佳右对齐方案。

输入

输入文件包含两行,每行一个字符串,最长50个字符。字符全部是大字字母。

输出

一行,为最佳对齐的得分。

样例

ALIGN.IN

AADDEFGGHC
ADCDEGH

ALIGN.OUT

9

解:

本题解法类似于

我们设f[i][j] a串从左到ib串从左到j的最大得分。

由于最左边的空格不扣分,所以我们可以读入串后将串反过来,这样便好处理了。不过这样最后的答案就不应该是f[lena, lenb]了(想想为什么)。f[lena,lenb]的答案是把最右边的空格的分扣去后的答案(现在的右边既为以前串的左边)。

一共有三种情况

1.a串和b串后都添加一个字母

如果这两个字母匹配,f[i+1, j+1] 就等于f[i, j] + 2

两个字母不匹配,f[i+1, j+1]便等于f[i, j]

2.b串后添k(k >= 1)个空格,在a串后添加一个字母

       枚举空格的长度k,如果f[i+k, j] < f[i, j] – 1f[i+k, j] 等与f[i, j] -1

3.a串后添k(k>=1)个空格,在b串后添加一个字母

       枚举空格的长度k,如果f[i, j+k] < f[i, j] – 1f[i, j+k] 等与f[i, j] -1

在转移的同时更新最大值max,最后的答案便为max.

程序如下:

var

    a, b : string;

    f : array[0 .. 50, 0 .. 50] of integer;

    max : integer;

   

procedure init;

var

    s : string;

    i, j : longint;

begin

    assign(input,'align.in'); reset(input);

    assign(output,'align.out'); rewrite(output);

    max := -1000;

    readln(a);

    s := a;

    for i := 1 to length(s) do

        a[length(s) - i + 1] := s[i];

    readln(b);

    s := b;

    for i := 1 to length(s) do

        b[length(s) - i + 1] := s[i];

    for i := 0 to length(a) do

        for j := 0 to length(b) do

            f[i, j] := -1000;

    f[0, 0] := 0;

end;

procedure dp;

var

    i, j, k : integer;

begin

    for i := 0 to length(a) do

        for j := 0 to length(b) do

            if f[i, j] > -1000 then begin

                for k := 1 to length(a) do

                    if i + k <= length(a) then

                        if f[i + k, j] < f[i, j] - 1 then begin

                            f[i + k, j] := f[i, j] - 1;

                            if f[i + k, j] > max then

                                max := f[i + k, j];

                        end;

                for k := 1 to length(b) do

                    if j + k <= length(b) then

                        if f[i, j + k] < f[i, j] - 1 then begin

                            f[i, j + k] := f[i, j] - 1;

                            if f[i, j + k] > max then

                                max := f[i, j + k];

                        end;

                if (i + 1 <= length(a)) and (j + 1 <= length(b)) then

                    if a[i + 1] = b[j + 1] then begin

                        if f[i + 1, j + 1] < f[i, j] + 2 then begin

                            f[i + 1, j + 1] := f[i, j] + 2;

                            if f[i + 1, j + 1] > max then

                                max := f[i + 1, j + 1];

                        end;

                    end

                    else begin

                        if f[i + 1, j + 1] < f[i, j] then begin

                            f[i + 1, j + 1] := f[i, j];

                            if f[i + 1, j + 1] > max then

                                max := f[i + 1, j + 1];

                        end;

                    end;

            end;

    writeln(max);

    close(input); close(output);

end;

begin

    init;

    dp;

end.

LCS

posted @ 2009-01-04 12:17  jesonpeng  阅读(292)  评论(0编辑  收藏  举报