【BZOJ1066】【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

【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.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值