【Description】
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
【Input】
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
【Output】
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
【Sample Input】
5 8 2
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
【Sample Output】
1
【Solution】
网络流基础题。源点向每个有蜥蜴的点连边,能跳出的所有点向汇点连边,每个石柱拆成两个点,容量为石柱高度,石柱之间从一个出去连向另一个进入即可。
代码如下:
const maxn=801; inf=1000000000;
type etype = record
go,next,v:longint;
end;
var n,m,d,cnt,ans:longint;
head,q,h,cur:array[0..maxn] of longint;
e:array[0..maxn*maxn] of etype;
map,mark:array[0..21,0..21] of longint;
function min(x,y:longint):longint;
begin if x<y then exit(x) else exit(y); end;
procedure insert(u,v,w:longint);
begin inc(cnt); e[cnt].go:=v; e[cnt].next:=head[u]; head[u]:=cnt; e[cnt].v:=w; end;
procedure ins(u,v,w:longint);
begin insert(u,v,w); insert(v,u,0); end;
function bfs():boolean;
var t,w,now,i:longint;
begin
fillchar(h,sizeof(h),255);
t:=0; w:=1; q[0]:=0; h[0]:=0;
while (t<w) do begin
now:=q[t]; inc(t);
i:=head[now];
while (i<>0) do begin
if (e[i].v>0) and (h[e[i].go]=-1) then begin
h[e[i].go]:=h[now]+1;
q[w]:=e[i].go; inc(w);
end;
i:=e[i].next;
end;
end;
exit(h[maxn]<>-1);
end;
function dfs(x,f:longint):longint;
var w,used,i:longint;
begin
if x=maxn then exit(f);
used:=0;
i:=head[x];
while (i<>0) do begin
if (e[i].v>0) and (h[e[i].go]=h[x]+1) then begin
w:=dfs(e[i].go,min(f-used,e[i].v));
dec(e[i].v,w); inc(e[i xor 1].v,w);
inc(used,w);
if used=f then exit(f);
end;
i:=e[i].next;
end;
if used<>0 then h[x]:=-1;
exit(used);
end;
procedure dinic();
begin while bfs() do dec(ans,dfs(0,inf)); end;
function judge(x1,y1,x2,y2:longint):boolean;
begin
if (x1<1) or (y1<1) or (x2<1) or (y2<1) then exit(false);
if (x1>n) or (y1>m) or (x2>n) or (y2>m) then exit(false);
if (sqr(x1-x2)+sqr(y1-y2)<=sqr(d)) and (map[x1,y1]<>0) and (map[x2,y2]<>0) then exit(true);
exit(false);
end;
procedure init();
var i,j,tot,x1,y1,x2,y2:longint;
st:string;
begin
readln(n,m,d);
for i:=1 to n do begin
readln(st);
for j:=1 to m do map[i,j]:=ord(st[j])-ord('0');
end;
tot:=0; cnt:=1;
for i:=1 to n do
for j:=1 to m do begin
inc(tot); mark[i,j]:=tot;
end;
for i:=1 to n do begin
readln(st);
for j:=1 to m do
if st[j]='L' then begin ins(0,mark[i,j],1); inc(ans); end;
end;
for i:=1 to d do
for j:=d+1 to n-d do begin
ins(mark[j,i]+400,maxn,inf);
ins(mark[j,m-i+1]+400,maxn,inf);
end;
for i:=1 to d do
for j:=1 to m do begin
ins(mark[i,j]+400,maxn,inf);
ins(mark[n-i+1,j]+400,maxn,inf);
end;
for x1:=1 to n do
for y1:=1 to m do
for x2:=x1-d to x1+d do
for y2:=y1-d to y1+d do
if judge(x1,y1,x2,y2) and ((x1<>x2) or (y1<>y2)) then ins(mark[x1,y1]+400,mark[x2,y2],inf);
for i:=1 to n do
for j:=1 to m do
if map[i,j]<>0 then ins(mark[i,j],mark[i,j]+400,map[i,j]);
end;
begin
init();
dinic();
writeln(ans);
end.