Description
假定我们有一个正方形的城市,拥有笔直的街道。城市由n行n列正方形的地块组成,每一块表示为一个街道或一堵墙。
碉堡就是一个小的城堡,有四个用于射击的口子。这四个口子分别朝着东、南、西、北方向。每一个口子都有一个用于射击的机关枪。
我们假定子弹力量很大,足以射到任何距离,并且破坏线路上的碉堡。另一方面,一堵墙非常牢固可以挡住子弹。
我们的目标就是在城市上放置一些碉堡,使得没有两个碉堡可以互相破坏。碉堡的合法配置就是没有两个碉堡在同一行或同一列上,除非它们之间至少有一堵墙隔在中间。在题目中我们考虑小的正方形城市(最多4×4)包含墙,使得子弹不能穿越。
下面的图示表示同一个区域,第一个图为空图,第二个和第三个图表示合法的配置,第四个图和第五个图表示违法的配置。对这个区域而言,合法配置的最大的碉堡的数量为5,第二个图显示了一种配置的方法,但还有另外的方法。
你的任务就是编程,对于给出的地图,计算碉堡的最大数量,可以合法配置在城市中。
Input
输入的第一行为n表示一个地图的大小,n最多为10,下面n行表示地图的每一列,一个‘.’表示空地,‘X’表示墙。
Output
输出一个最大的碉堡数量,使得在城市中可以合法配置。
Sample Input
4
.X..
….
XX..
….
Sample Output
5
var
i,n,m,j,k,tot:longint;
map:array[0..256,0..256] of boolean;
e:array[0..256,0..256,1..2] of longint;
b:array[0..12] of longint;
cover:array[0..256] of boolean;
link,ans:array[0..256] of longint;
procedure test(a,b,c,d,f:longint);
var
i:longint;
begin
if d=1 then
for i:=a to b do
e[c,i,d]:=f;
if d=2 then
for i:=a to b do
e[i,c,d]:=f;
end;
function find(i,x:longint):boolean;
var
k,q:longint;
begin
find:=true;
for k:=1 to x do
if map[i,k] and not(cover[k]) then
begin
q:=link[k]; link[k]:=i; cover[k]:=true;
if (q=0) or (find(q,x)) then exit;
link[k]:=q;
end;
find:=false;
end;
procedure main(x:longint);
var
i:longint;
begin
for i:=1 to x do
begin
fillchar(cover,sizeof(cover),false);
find(i,x);
end;
end;
procedure print(x,a:longint);
var
i,s:longint;
begin
s:=0;
for i:=1 to x do
if link[i]<>0 then inc(s);
writeln(s);
end;
procedure init(x,y:longint);
var
n,m,i,j:longint;
check:array[0..51,0..51] of boolean;
a:array[0..51,0..51] of char;
c,d,tot,ff,f,max:longint;
begin
n:=y;
b[x]:=n;
fillchar(check,sizeof(check),false);
fillchar(e,sizeof(e),0);
fillchar(a,sizeof(a),'0');
c:=0;
tot:=0;
m:=n;
for i:=1 to n do
begin
for j:=1 to m do
begin
read(a[i,j]);
if a[i,j]='.' then check[i,j]:=true;
end;
readln;
end;
for i:=1 to n+1 do
for j:=1 to m+1 do
begin
if (c=0) and (a[i,j]='.') then begin
c:=j; inc(tot);
end;
if not(check[i,j]) then
if c<>0 then
begin
test(c,j-1,i,1,tot);
c:=0;
end;
end;
c:=0;
ff:=tot;
tot:=0;
for i:=1 to m+1 do
for j:=1 to n+1 do
begin
if (c=0) and (a[j,i]='.') then begin
c:=j; inc(tot);
end;
if not(check[j,i]) then
if c<>0 then
begin
test(c,j-1,i,2,tot);
c:=0;
end;
end;
f:=tot;
fillchar(map,sizeof(map),0);
fillchar(link,sizeof(link),0);
for i:=1 to n do
for j:=1 to m do
if (e[i,j,1]<>0) and (e[i,j,2]<>0) then map[e[i,j,1],e[i,j,2]]:=true;
if ff>f then max:=ff
else max:=f;
main(max);
print(max,x);
end;
begin
readln(n);
if n<>0 then init(i,n);
end.