【BZOJ1066】【SCOI2007】蜥蜴

来源:互联网 发布:html软件 编辑:程序博客网 时间:2024/04/29 23:57

【Description】

  在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。


【Input】

  输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。


【Output】

  输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。


【Sample Input】

5 8 20000000002000000003211000200000000000000..................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.
0 0
原创粉丝点击