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.
View Code

 

posted @ 2016-03-01 13:23  QTY_YTQ  阅读(122)  评论(0编辑  收藏