【解题思路】

  考虑拆点,把每根石柱拆成两个点,具体可以理解为石柱底部和石柱顶部,能爬到石柱顶部的蜥蜴只有有限只,而且蜥蜴只有爬到了石柱顶部才能跳到其他石柱的底部。

  这样,考虑如下建图:

  将每个有蜥蜴的石柱底部和源点连边,容量为1;

  将每个可以跳出边界的石柱顶部和汇点连边,容量为∞;

  将每根石柱顶底相连,容量为该石柱最大承受蜥蜴个数;

  将可以相互跳达的任意两根石柱顶底相连,容量为∞。

  这样,该图的最大流即为最多可逃脱蜥蜴数,最终答案即为总蜥蜴数-最大流,复杂度o(r3c3d2)。

【参考代码】

  1 #include <bits/stdc++.h>
  2 #define range(i,low,high) for(register int i=(low);i<(high);++i)
  3 #define dange(i,high,low) for(register int i=(high);i>(low);--i)
  4  
  5 //#define __debug
  6 #ifdef __debug
  7     #define __function__(type) type
  8     #define __procedure__      void
  9 #else
 10     #define __function__(type) __attribute__((optimize("-O2"))) inline type
 11     #define __procedure__      __attribute__((optimize("-O2"))) inline void
 12 #endif
 13  
 14 using namespace std;
 15  
 16 static const int N=800,M=50000,INF=0x7f7f7f7f;
 17 static int r,c,d,cardE=0; int hed[N+5],h[25][25];
 18  
 19 struct edge
 20 {
 21     int fr,to,cap,nxt;
 22     edge(
 23         const int&f=0,const int&t=0,
 24         const int&c=0,const int&x=0
 25     ):fr(f),to(t),cap(c),nxt(x) {}
 26 }edg[M<<2|3];
 27  
 28 __procedure__ addedge(
 29     const int&fr,const int&to,const int&cp
 30 )
 31 {
 32     edg[cardE]=edge(fr,to,cp,hed[fr]),hed[fr]=cardE++;
 33 }
 34 __procedure__ add_edge(
 35     const int&fr,const int&to,const int&cp
 36 )
 37 {
 38     addedge(fr,to,cp),addedge(to,fr,0);
 39 }
 40  
 41 //SAP {
 42 static const int S=0,T=801;
 43 int aug[N+5],cur[N+5],dis[N+5],gap[N+5],path[N+5];
 44  
 45 __function__(int) augment()
 46 {
 47     for(int i=T;i!=S;i=edg[path[i]].fr)
 48     {
 49         edg[path[i]].cap-=aug[T],edg[path[i]^1].cap+=aug[T];
 50     }
 51     return aug[T];
 52 }
 53  
 54 __function__(int) SAP(const int&N)
 55 {
 56     memset(aug,0,sizeof aug),memset(gap,0,sizeof gap);
 57     memset(dis,0,sizeof dis),aug[S]=INF,gap[0]=N; int ret=0;
 58     range(i,1,max(N,T)+1) cur[i]=hed[i];
 59     for(int fr=S;dis[S]<N;)
 60     {
 61         if(fr==T) fr=S,ret+=augment(); bool flag=1;
 62         for(int i=cur[fr];~i;i=edg[i].nxt)
 63         {
 64             int to=edg[i].to;
 65             if(edg[i].cap&&dis[fr]==dis[to]+1)
 66             {
 67                 aug[to]=min(aug[fr],edg[i].cap),
 68                 path[to]=cur[fr]=i,fr=to,flag=0; break;
 69             }
 70         }
 71         if(flag)
 72         {
 73             if(!--gap[dis[fr]]) break; dis[fr]=N;
 74             for(int i=hed[fr];~i;i=edg[i].nxt) if(edg[i].cap)
 75             {
 76                 dis[fr]=min(dis[fr],dis[edg[i].to]+1);
 77             }
 78             ++gap[dis[fr]],cur[fr]=hed[fr];
 79             if(fr!=S) fr=edg[path[fr]].fr;
 80         }
 81     }
 82     return ret;
 83 }
 84 //} SAP
 85  
 86 __function__(bool) ok(const int&x,const int&y)
 87 {
 88     return x+d>=r||x<d||y+d>c||y<=d;
 89 }
 90  
 91 __function__(int) calc(const int&x,const int&y,const bool&up)
 92 {
 93     return x*c+y+up*(N>>1);
 94 }
 95  
 96 int main()
 97 {
 98     scanf("%d%d%d",&r,&c,&d); int cnt=0;
 99     memset(hed,-1,sizeof hed);
100     range(i,0,r) range(j,1,c+1)
101     {
102         while(!isdigit(h[i][j]=getchar()));
103         add_edge(calc(i,j,0),calc(i,j,1),h[i][j]-='0');
104     }
105     range(i,0,r) range(j,1,c+1)
106     {
107         char ch=getchar();
108         for(;ch!='.'&&ch!='L';ch=getchar());
109         if(ch=='L') add_edge(S,calc(i,j,0),1),++cnt;
110     }
111     range(i,0,r) range(j,1,c+1) if(ok(i,j))
112     {
113         add_edge(calc(i,j,1),T,INF);
114     }
115     range(i,0,r) range(j,1,c+1) range(k,-d,d+1)
116     {
117         int rest=d-abs(k);
118         range(l,-rest,rest+1) if(k||l)
119         {
120             int x=i+k,y=j+l;
121             if(x>=0&&x<r&&y>0&&y<=c&&h[i][j]&&h[x][y])
122             {
123                 add_edge(calc(i,j,1),calc(x,y,0),INF);
124             }
125         }
126     }
127     return printf("%d\n",cnt-SAP(r*c+1<<1)),0;
128 }
View Code