最大流板子题。
对于每根柱子,建两个点ai,bi,建边(ai,bi,柱子高度)
对于距离不超过d的两根柱子i,j,建边(bi,aj,inf)
对于起始位置在i的每个蜥蜴,建边(S,ai,1)
对于能跳出地图的柱子i,建边(bi,E,inf)
然后跑dinic即可
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int maxn=23,inf=0x3f3f3f3f; struct Edge{ int a,b,v; int ne; }eg[maxn*maxn*maxn*maxn*4]; int R,C,D,pcnt,rcnt,ecnt; int map[maxn][maxn][2]; int rd[100][2]; int egh[maxn*maxn*2],P[maxn][maxn][2]; int deep[maxn*maxn*2]; inline void addedge(int a,int b,int v){ eg[ecnt].a=a;eg[ecnt].b=b;eg[ecnt].v=v;eg[ecnt].ne=egh[a];egh[a]=ecnt++; eg[ecnt].a=b;eg[ecnt].b=a;eg[ecnt].v=0;eg[ecnt].ne=egh[b];egh[b]=ecnt++; } bool bfs(){ queue<int> q;memset(deep,0,sizeof(deep)); q.push(1);deep[1]=1; while(!q.empty()){ int p=q.front();q.pop(); for(int i=egh[p];i!=-1;i=eg[i].ne){ if(eg[i].v&&!deep[eg[i].b]){ q.push(eg[i].b);deep[eg[i].b]=deep[p]+1; } } }return deep[2]; } int dinic(int x,int l){ if(x==2) return l;int tmp=l; for(int i=egh[x];i!=-1;i=eg[i].ne){ if(deep[eg[i].b]!=deep[x]+1||!eg[i].v) continue; int re=dinic(eg[i].b,min(eg[i].v,l)); if(!re) deep[eg[i].b]=0; tmp-=re;eg[i].v-=re;eg[i^1].v+=re; if(!tmp) break; }return l-tmp; } int main(){ int i,j,k,ans=0; char s[maxn]; //freopen("1066.in","r",stdin); scanf("%d%d%d",&R,&C,&D); for(i=1;i<=R;i++){ scanf("%s",s+1); for(j=1;j<=C;j++) map[i][j][0]=s[j]-'0'; } for(i=1;i<=R;i++){ scanf("%s",s+1); for(j=1;j<=C;j++) map[i][j][1]=(s[j]=='L'?1:0); } for(i=-D;i<=D;i++){ for(j=-D;j<=D;j++){ if(i*i+j*j<=D*D){rd[rcnt][0]=i;rd[rcnt++][1]=j;} } } pcnt=2;memset(egh,-1,sizeof(egh)); for(i=1;i<=R;i++) for(j=1;j<=C;j++) if(map[i][j][0]){ P[i][j][0]=++pcnt;P[i][j][1]=++pcnt;addedge(P[i][j][0],P[i][j][1],map[i][j][0]); if(map[i][j][1]) {addedge(1,P[i][j][0],1);ans++;} } for(i=1;i<=R;i++){ for(j=1;j<=C;j++){ if(!map[i][j][0]) continue; bool b=0; for(k=0;k<rcnt;k++){ int ii=i+rd[k][0],jj=j+rd[k][1]; if(ii<=0||ii>R||jj<=0||jj>C) b=1; else if(map[ii][jj]) addedge(P[i][j][1],P[ii][jj][0],inf); }if(b) addedge(P[i][j][1],2,inf); } } while(bfs()) ans-=dinic(1,inf); printf("%d",ans); }