USACO题库2.1.1 The Castle城堡 题解

Posted John_pascal

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了USACO题库2.1.1 The Castle城堡 题解相关的知识,希望对你有一定的参考价值。

题目描述:

我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票)。结果这张彩票让他获得了这次比赛唯一的奖品——坐落于爱尔兰郊外的一座梦幻般的城堡!


喜欢吹嘘的农夫约翰立刻回到有着吹嘘传统的威斯康辛老家开始吹嘘了, 农夫约翰想要告诉他的奶牛们关于他城堡的一切。他需要做一些吹嘘前的准备工作:比如说知道城堡有多少个房间,每个房间有多大。另外,农夫约翰想要把一面单独的墙(指两个单位间的墙)拆掉以形成一个更大的房间。 你的工作就是帮农夫约翰做以上的准备,算出房间数与房间的大小。

城堡的平面图被划分成M*N(1 <=M,N<=50)个正方形的单位,一个这样的单位可以有0到4面墙环绕。城堡周围一定有外墙环绕以遮风挡雨。(就是说平面图的四周一定是墙。)

请仔细研究下面这个有注解的城堡平面图:

     1   2   3   4   5   6   7
   #############################
 1 #   |   #   |   #   |   |   #
   #####---#####---#---#####---#   
 2 #   #   |   #   #   #   #   #
   #---#####---#####---#####---#
 3 #   |   |   #   #   #   #   #   
   #---#########---#####---#---#
 4 # ->#   |   |   |   |   #   #   
   ############################# 


 # =墙壁    -,| = 没有墙壁
 -> =指向一面墙,这面墙推掉的话我们就有一间最大的新房间

友情提示,这个城堡的平面图是7×4个单位的。一个“房间”的是平面图中一个由“#”、“-”、“|”围成的格子(就是图里面的那一个个的格子)。比如说这个样例就有5个房间。(大小分别为9、7、3、1、8个单位(排名不分先后))


移去箭头所指的那面墙,可以使2个房间合为一个新房间,且比移去其他墙所形成的房间都大。



INPUT FORMAT: 

第一行有两个整数:M和N 城堡的平面图用一个由数字组成的矩阵表示,一个数字表示一个单位,矩阵有N行M列。输入与样例的图一致。
每一个单位的数字告诉我们这个单位的东西南北是否有墙存在。每个数字是由以下四个整数的某个或某几个加起来的(四面都没有墙的话,这个数字应该为0)。
1: 在西面有墙
2: 在北面有墙
4: 在东面有墙
8: 在南面有墙
城堡内部的墙会被规定两次。比如说(1,1)南面的墙,亦会被标记为(2,1)北面的墙。


OUTPUT FORMAT:
输出包含如下4行:
第 1 行: 城堡的房间数目。
第 2 行: 最大的房间的大小
第 3 行: 移除一面墙能得到的最大的房间的大小
第 4 行: 移除哪面墙可以得到面积最大的新房间。

选择最佳的墙来推倒。有多解时选最靠西的,仍然有多解时选最靠南的。同一格子北边的墙比东边的墙更优先。
用该墙的南邻单位的北墙或西邻单位的东墙来表示这面墙,方法是输出邻近单位的行数、列数和墙的方位("N"(北)或者"E"(东))。


样例输入:
7 4
11 6 11 6 3 10 6
7 9 6 13 5 15 5
1 10 12 7 13 7 5
13 11 10 8 10 12 13
样例输出:
5
9
16
4 1 E

 

前两问可以用bfs或者dfs解决,然后第3问我们可以建立一个二维数组的表,f[i,j]表示每一个格子的房间数目,然后注意这时搜索移除的墙,一定要按照“最佳的墙”来推倒。先搜索最靠西的(从左往右),然后再选最考南的(从下往上)。所以搜索的顺序应该是

for i:=1 to m do
      for j:=n downto 1 do
             for k:=1 to 2 do
k搜索的是北墙与东墙。其实这道题并不难,不要被题目的长度或者问题的难度所吓倒,而要迎刃而解。


代码:

const
        d:array[1..4]of longint=(1,2,4,8);
        dx:array[1..4]of longint=(0,-1,0,1);
        dy:array[1..4]of longint=(-1,0,1,0);
var
        a:array[1..3000] of longint;
        bz:array[0..51,0..51,1..4]of boolean;
        f:array[0..51,0..51]of longint;
        m,n,ans1,ans2,ch,max,ans,total:longint;

procedure readdata;
var
        k,num,i,j:longint;
begin
        readln(m,n);
        for i:=1 to n do
                for j:=1 to m do
                begin
                        read(num);
                        for k:=4 downto 1 do
                                if (num>=d[k]) then
                                begin
                                        dec(num,d[k]);
                                        bz[i,j,k]:=true;
                                end;
                end;
end;

procedure dfs(i,j:longint);
var
        x,y,k:longint;
begin
        f[i,j]:=total;

        for k:=1 to 4 do
        begin
                x:=i+dx[k];
                y:=j+dy[k];
                if (x>0) and (x<=n) and (y>0) and (y<=m) and not bz[i,j,k] and (f[x,y]=0) then
                begin
                        inc(a[total]);
                        dfs(x,y);
                end;
        end;
end;

procedure bfs(x,y:Longint);
var
        head,tail,i,xx,yy:Longint;
        data:array[1..2500,1..2] of longint;
begin
        f[x,y]:=total;

        fillchar(d,sizeof(d),0);

        head:=0;
        tail:=1;

        data[1,1]:=x;
        data[1,2]:=y;

        while head<tail do
        begin
                inc(head);
                for i:=1 to 4 do
                begin
                        xx:=data[head,1]+dx[i]; yy:=data[head,2]+dy[i];

                        if (xx>0) and (xx<=n) and (yy>0) and (yy<=m) and not bz[data[head,1],data[head,2],i] and (f[xx,yy]=0) then
                        begin
                                inc(a[total]);

                                inc(tail);
                                data[tail,1]:=xx;
                                data[tail,2]:=yy;

                                f[xx,yy]:=total;
                        end;
                end;
        end;
end;

procedure print;
begin
        writeln(ans);
        write(ans1,' ',ans2,' ');
        if ch=2 then writeln('N') else writeln('E');
end;

procedure work;
var
        x,y,k,i,j:longint;
begin
        total:=0;
        max:=0;

        for i:=1 to n do
                for j:=1 to m do
                        if (f[i,j]=0) then
                        begin
                                inc(total);
                                a[total]:=1;

                                //dfs(i,j);
                                bfs(i,j);

                                if a[total]>max then max:=a[total];
                        end;

        writeln(total);
        writeln(max);

        ans:=0;
        for j:=1 to m do
                for i:=n downto 1 do
                        for k:=2 to 3 do
                        begin
                                x:=i+dx[k];
                                y:=j+dy[k];
                                if (x>0) and (y<=m) and (f[i,j]<>f[x,y]) and (a[f[i,j]]+a[f[x,y]]>ans) then
                                begin
                                        ans:=a[f[i,j]]+a[f[x,y]];

                                        ans1:=i;
                                        ans2:=j;

                                        ch:=k;
                                end;
                        end;
        print;
end;

begin
        readdata;

        work;
end.

以上是关于USACO题库2.1.1 The Castle城堡 题解的主要内容,如果未能解决你的问题,请参考以下文章

洛谷P1457 城堡 The Castle

搜索DFS之城堡 The Castle

P1457 城堡 The Castle

洛谷P1457 城堡 The Castle

洛谷—— P1457 城堡 The Castle

USACO The Castle