【解题思路】
考虑拆点,把每根石柱拆成两个点,具体可以理解为石柱底部和石柱顶部,能爬到石柱顶部的蜥蜴只有有限只,而且蜥蜴只有爬到了石柱顶部才能跳到其他石柱的底部。
这样,考虑如下建图:
将每个有蜥蜴的石柱底部和源点连边,容量为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 }
We Secure, We Contain, We Protect.