BZOJ 1066:[SCOI2007]蜥蜴(最大流)
蜥蜴
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
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=4
分析:
由于每个柱子能经过蜥蜴的次数有限,可将一个柱子拆为两个点Ai,Bi,从Bi到Ai连一条边,容量为柱子高度。如果柱子j与i距离符合要求,就连一条Ai到Bj容量无限的边,如果一开始该柱子上有蜥蜴就从源点连一条容量为1的边指向柱子i,如果柱子i到边界距离不超过d就向汇点连一条容量无限的边,跑一遍dinic后用蜥蜴数减最大流即为答案。
代码:
program work; var f,map:array[0..801,0..801]of longint; q:array[0..5000]of longint; a,b,c,h:array[0..801]of longint; n,i,m,j,s,t,d,ans,k,v,flow:longint; ch:char; function min(x,y:longint):longint; begin if x<y then min:=x else min:=y; end; function bfs:boolean; var l,r,x,i:longint; begin fillchar(h,sizeof(h),0); l:=0; r:=1; q[1]:=s;h[s]:=1; while l<r do begin inc(l); x:=q[l]; for i:=0 to t do if (f[x,i]>0)and(h[i]=0) then begin h[i]:=h[x]+1; inc(r);q[r]:=i; end; end; if h[t]=0 then exit(false) else exit(true); end; function dfs(x,flow:longint):longint; var d,i:longint; begin if x=t then exit(flow); for i:=0 to t do if (h[i]=h[x]+1)and(f[x,i]>0) then begin d:=dfs(i,min(f[x,i],flow)); if d<>0 then begin inc(f[i,x],d);dec(f[x,i],d);exit(d); end; end; exit(0); end; begin readln(n,m,d);fillchar(f,sizeof(f),0); for i:=1 to n do begin for j:=1 to m do begin read(ch); if ch<>'0' then begin inc(t); a[t]:=i; b[t]:=j;c[t]:=ord(ch)-48; map[i,j]:=t;end; end; readln; end; for i:=1 to n do begin for j:=1 to m do begin read(ch); if ch='L' then begin f[0,t+map[i,j]]:=1; inc(k); end; end; readln; end; for i:=1 to t do begin f[i+t,i]:=c[i]; for j:=1 to t do if j<>i then begin if sqr(a[i]-a[j])+sqr(b[i]-b[j])<=d*d then f[i,j+t]:=k; end; if (a[i]-d<=0)or(a[i]+d>n)or(b[i]-d<=0)or(b[i]+d>m) then f[i,t*2+1]:=k; end; ans:=0; s:=0; t:=t*2+1; while bfs do begin flow:=dfs(s,maxlongint div 3); while flow<>0 do begin inc(ans,flow); flow:=dfs(s,maxlongint div 3); end; end; writeln(k-ans); end.