城堡
题目描述
我们憨厚的USACO主人公农夫约翰(Farmer John)以无法想象的运气,在他生日那天收到了一份特别的礼物:一张“幸运爱尔兰”(一种彩票)。结果这张彩票让他获得了这次比赛唯一的奖品——坐落于爱尔兰郊外的一座梦幻般的城堡!
喜欢吹嘘的农夫约翰立刻回到有着吹嘘传统的威斯康辛老家开始吹嘘了, 农夫约翰想要告诉他的奶牛们关于他城堡的一切。他需要做一些吹嘘前的准备工作:比如说知道城堡有多少个房间,每个房间有多大。另外,农夫约翰想要把一面单独的墙(指两个单位间的墙)拆掉以形成一个更大的房间。 你的工作就是帮农夫约翰做以上的准备,算出房间数与房间的大小。
城堡的平面图被划分成M*N(1 <=M,N<=50)个正方形的单位,一个这样的单位可以有0到4面墙环绕。城堡周围一定有外墙环绕以遮风挡雨。(就是说平面图的四周一定是墙。)
请仔细研究下面这个有注解的城堡平面图:
友情提示,这个城堡的平面图是7×4个单位的。一个“房间”的是平面图中一个由“#”、“-”、“|”围成的格子(就是图里面的那一个个的格子)。比如说这个样例就有5个房间。(大小分别为9、7、3、1、8个单位(排名不分先后))
移去箭头所指的那面墙,可以使2个房间合为一个新房间,且比移去其他墙所形成的房间都大。(原文为:Removing the wall marked by the arrow merges a pair of rooms to make the largest possible room that can be made by removing a single wall. )
城堡保证至少有2个房间,而且一定有一面墙可以被移走。
分析:搜索,把属于同一个的点标记,在另一个数组里存每个点所属房间的大小,最后枚举每个点,看拆除一面墙后两个房间合并的最大值是否大于max。
代码
const
maxn=50;
dx:array[1..4] of -1..1=(-1,0,1,0);
dy:array[1..4] of -1..1=(0,1,0,-1);
var
a:array[0..maxn,0..maxn,1..4] of boolean;
b,c:array[0..maxn,0..maxn] of longint;
f:array[0..maxn,0..maxn] of boolean;
sum:array[0..5000] of longint;
n,m,i,j,x,max,ans1,ans2,ansx,ansy:longint;
ansd:char;
function check(x,y,x1,y1,d:longint):boolean;
begin
check:=true;
inc(d);
if d>4 then d:=1;
if (f[x,y]) or (a[x1,y1,d]) then exit(False);
end;
procedure dfs(x,y:longint);
var
i:longint;
begin
for i:=1 to 4 do
if check(x+dx[i],y+dy[i],x,y,i) then
begin
inc(max);
f[x+dx[i],y+dy[i]]:=true;
dfs(x+dx[i],y+dy[i]);
end;
c[x,y]:=ans2+1;
end;
begin
readln(m,n);
for i:=1 to n do
for j:=1 to m do
begin
read(x);
if x>=8 then begin dec(x,8);a[i,j,4]:=true;a[i+1,j,2]:=true;end;
if x>=4 then begin dec(x,4);a[i,j,3]:=true;a[i,j+1,1]:=true;end;
if x>=2 then begin dec(x,2);a[i,j,2]:=true;a[i-1,j,4]:=true;end;
if x>=1 then begin dec(x);a[i,j,1]:=true;a[i,j-1,3]:=true;end;
end;
for i:=1 to n do
for j:=1 to m do
if not f[i,j] then
begin
max:=1;
f[i,j]:=true;
dfs(i,j);
inc(ans2);
sum[ans2]:=max;
if max>ans1 then ans1:=max;
end;
writeln(ans2);
writeln(ans1);
max:=0;
for i:=1 to n do
for j:=1 to m do
b[i,j]:=sum[c[i,j]];
for i:=1 to m do
for j:=n downto 1 do
begin
if a[j,i,2] then
if (b[j,i]+b[j-1,i]>max) and (j<>1) and (c[j,i]<>c[j-1,i])then
begin
max:=b[j,i]+b[j-1,i];
ansd:='N';
ansx:=j;
ansy:=i;
end;
if a[j,i,3] then
if (b[j,i]+b[j,i+1]>max) and (i<>m) and (c[j,i]<>c[j,i+1]) then
begin
max:=b[j,i]+b[j,i+1];
ansd:='E';
ansx:=j;
ansy:=i;
end;
end;
writeln(max);
writeln(ansx,' ',ansy,' ',ansd);
end.