【NOIP提高組】C

Description

給出一個H的行和W列的網格。第i行第j列的狀態是由一個字母的A[i][j]表示,如下:
“.” 此格爲空。
“o” 此格包含一個機器人。
“E” 此格包含一個出口,保證出口在整個網格中有且只有一個
每次可以選擇上,下,左,右之一的方向,將所有剩餘的機器人向這個方向移動一個格子,如果一個機器人被移出了網格,那麼這個機器人會爆炸,並立即消失。如果一個機器人移動到出口所在的格子,機器人將獲救,並消失,最多有多少機器人獲救。

Solution

我們設lrud 分別表示機器人向四個方向的位移分別是多少,在範圍外的機器人就是已經爆炸了,或是被解救了(詳見圖)。
這裏寫圖片描述
紅色區域已經沒有機器人了,這是由於移出邊界爆炸或者在這之前獲救,而黃色區域的機器人已經獲救了(顯然如果沒有獲救,那麼一定不優,因爲犧牲了紅色區域之後,黃色區域是一定能到達出口的),那麼我們可以通過增加可行範圍,即增加黃色區域的邊界,進而對答案不斷地推進。假設我們在最上一行犧牲掉一行,那麼在下一行就一定能夠選到一行。

當我們犧牲掉上一行時,下面紫色的一行就能被必定選上(正確性已證),同樣推及四個方向就能弄出四條遞推式,遞推式其實不太難,在這裏就不詳細寫出來了。由於1004 會爆空間,所以要開滾動數組。

Code

var
    map:array[0..101,0..101] of char;
    f:array[0..1,0..101,0..101,0..101] of longint;
    x,y:array[0..101,0..101] of longint;
    s:array[1..4] of longint;
    n,m,i,j,l,r,u,d,ex,ey,ans,z:longint;
function max(x,y:longint):longint;
begin
    if x>y then exit(x);exit(y);
end;
function min(x,y:longint):longint;
begin
    if x<y then exit(x);exit(y);
end;
function getl(h1,h2,l1:longint):longint;
begin
    if ey-l-1<=r then exit(0);
    h1:=min(h1,n-u);h2:=max(h2,d);
    exit(x[h1][l1]-x[h2][l1]);
end;
function getr(h1,h2,l1:longint):longint;
begin
    if m-l<=r+ey then exit(0);
    h1:=min(h1,n-u);h2:=max(h2,d);
    exit(x[h1][l1]-x[h2][l1]);
end;
function getu(h1,l1,l2:longint):longint;
begin
    if ex-u-1<=d then exit(0);
    l1:=min(l1,m-l);l2:=max(l2,r);
    exit(y[h1][l1]-y[h1][l2]);
end;
function getd(h1,l1,l2:longint):longint;
begin
    if n-u<=d+ex then exit(0);
    l1:=min(l1,m-l);l2:=max(l2,r);
    exit(y[h1][l1]-y[h1][l2]);
end;
begin
    readln(n,m);
    for i:=1 to n do
    begin
        for j:=1 to m do
        begin
            read(map[i,j]);
            x[i,j]:=x[i-1,j];y[i,j]:=y[i,j-1];
            if map[i,j]='E' then
            begin
                ex:=i;ey:=j;
                s[1]:=i-1;s[2]:=j-1;s[3]:=n-i;s[4]:=m-j;
            end
            else if map[i,j]='o' then
            begin
                inc(x[i,j]);inc(y[i,j]);
            end;
        end;
        readln;
    end;
    for l:=0 to s[2] do
    begin
        z:=1-z;
        fillchar(f[1-z],sizeof(f[1-z]),0);
        for r:=0 to s[4] do
            for u:=0 to s[1] do
              for d:=0 to s[3] do
              begin
                  f[z,r,u,d+1]:=max(f[z,r,u,d+1],f[z,r,u,d]+getd(ex+d+1,ey+r,ey-l-1));

                  f[z,r+1,u,d]:=max(f[z,r+1,u,d],f[z,r,u,d]+getr(ex+d,ex-u-1,ey+r+1));

                  f[z,r,u+1,d]:=max(f[z,r,u+1,d],f[z,r,u,d]+getu(ex-u-1,ey+r,ey-l-1));

                  f[1-z,r,u,d]:=max(f[1-z,r,u,d],f[z,r,u,d]+getl(ex+d,ex-u-1,ey-l-1));
                  ans:=max(ans,f[z,r,u,d]);
              end;
    end;
    writeln(ans);
end.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章