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城堡 题解的主要内容,如果未能解决你的问题,请参考以下文章