题意
给你两个图,一个用0,1,2,3表示,一个用 L 或 . 表示。其中用L表示的图中,有L的位置表示有蜥蜴,没有L的位置表示没有蜥蜴。用数字表示的图中,数字表示当前位置柱子的高度,每次一个蜥蜴可以从一个柱子跳到距离d以内的另外一个柱子,每跳跃一次,当前柱子的高度就减一,问最后会有多少只蜥蜴被困在里面。
解
将柱子拆点,每个蜥蜴向其曼哈顿距离内点连边,跑最大流
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<queue>
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Set(a,b) memset(a,b,sizeof(a))
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
using namespace std ;
const int N=810 ,M=7500 ,INF=0x3f3f3f3f ;
template <class T>inline void read(T &x){
x=0 ;char c=getchar();int f(0 );
while (c>'9' ||c<'0' )f|=(c=='-' ),c=getchar();
while (c>='0' &&c<='9' )x=(x<<1 )+(x<<3 )+(c^48 ),c=getchar();
x=f?-x:x;
}
template <class T>inline void chkmin(T &a,T b){a=a>b?b:a;}
template <class T>inline void chkmax(T &a,T b){a=a<b?b:a;}
int Begin[N],Next[M<<1 ],to[M<<1 ],f[M<<1 ],e=1 ,n,m,d;
inline void add(int x,int y,int z){
to[++e]=y,Next[e]=Begin[x],Begin[x]=e,f[e]=z;
}
struct isap{
int s,t,gap[N],d[N],p[N],cur[N];
#define Retr(u) for(u=t;u^s;u=to[p[u]^1])
inline void init(){
queue <int > q;
For(i,1 ,t)d[i]=INF,gap[i]=0 ,cur[i]=Begin[i];
gap[0 ]=1 ;d[t]=0 ;q.push(t);
while (!q.empty()){
int r=q.front();q.pop();
Rep(i,r)
if (f[i^1 ]&&d[v]>d[r]+1 )
++gap[d[v]=d[r]+1 ],q.push(v);
}
}
inline int Augment(){
int u,a=INF;
Retr(u)chkmin(a,f[p[u]]);
Retr(u)f[p[u]]-=a,f[p[u]^1 ]+=a;
return a;
}
inline int Maxflow(int _s,int _t){
int i,u=s=_s,flow=0 ;t=_t;
init();
while (d[s]<t){
if (u==t)flow+=Augment(),u=s;
for (i=cur[u];i;i=Next[i])
if (f[i]&&d[u]==d[to[i]]+1 )break ;
if (!i){
if (--gap[d[u]]==0 )break ;
d[u]=t;cur[u]=Begin[u];
Rep(i,u)
if (f[i])chkmin(d[u],d[v]+1 );
++gap[d[u]];
if (u^s)u=to[p[u]^1 ];
}else cur[u]=i,p[u=to[i]]=i;
}
return flow;
}
}F;
char ch[25 ];
char st[25 ][25 ];
struct node{
int x,y,z;
node(int x=0 ,int y=0 ,int z=0 ):x(x),y(y),z(z){}
}P[N];
inline bool can(node a,node b,int d){
int l=abs (a.x-b.x)+abs (a.y-b.y);
if (l<=d)return 1 ;
return 0 ;
}
inline bool out(node a,int d){
return a.x+d>n || a.x-d<1 || a.y+1 +d>m || a.y-d<0 ;
}
inline void work(){
int totz(0 ),totl(0 );
read(n),read(d);
Set(Begin,0 ),e=1 ,m=0 ;
For(i,1 ,n){
scanf ("%s" ,ch);
if (!m)m=strlen (ch);
For(j,0 ,m-1 )
if (ch[j]!='0' )
P[++totz]=node(i,j,ch[j]-'0' );
}
For(i,1 ,n)
scanf ("%s" ,st[i]);
int s_=totz*2 +1 ,t_=s_+1 ;
For(i,1 ,totz){
add(i,i+totz,P[i].z),add(i+totz,i,0 );
For(j,1 ,totz)
if (i!=j)
if (can(P[i],P[j],d))
add(i+totz,j,P[i].z),add(j,i+totz,0 );
if (st[P[i].x][P[i].y]=='L' )add(s_,i,1 ),add(i,s_,0 ),totl++;
if (out(P[i],d))add(i+totz,t_,P[i].z),add(t_,i+totz,0 );
}
int ans=totl-F.Maxflow(s_,t_);
if (ans==0 )
printf ("no " );
else printf ("%d " ,ans);
if (ans==1 ||ans==0 )puts ("lizard was left behind." );
else puts ("lizards were left behind." );
}
int main(){
int T;
read(T);
For(i,1 ,T)
printf ("Case #%d: " ,i),work();
return 0 ;
}