题目链接:https://www.luogu.com.cn/problem/P2472
n ∗ m n*m n∗m个格子,每个格子的石柱高度不同,蜥蜴可以跳到距离不超过 d d d的石柱处,并且先前所站的石柱高度减一,为0则不能站,然后求有多少只蜥蜴不可以逃脱。
考虑网络流,每只蜥蜴表示一个流,将每个石柱分成入点和出点,然后入点连出点流量为石柱高度,然后每个可以走的点之间出点连入点无限,之后有蜥蜴的柱子原点连入点流量为1,可以逃脱的出点连汇点。
然后dinic即可。
#include
#include
#include
#include
#define p(x,y,w) ((((x)-1)*m+(y))*2-w)
using namespace std;
const int N=1e5+10,M=4e5+10,inf=2147483647/3;
struct node{
int to,next,w;
}a[M];
int n,m,tot=1,s,t,d,ans;
int ls[N],dep[N];
char str[30];
queue<int> q;
void addl(int x,int y,int w){
a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;
a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;
return;
}
int dis(int x1,int y1,int x2,int y2)
{return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);}
void connect(int x,int y){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(dis(x,y,i,j)<=d*d&&(i!=x||j!=y))
addl(p(x,y,1),p(i,j,0),inf);
return;
}
bool bfs(){
memset(dep,0,sizeof(dep));
while(!q.empty())q.pop();
q.push(s);dep[s]=1;
while(!q.empty()){
int x=q.front();q.pop();
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(!a[i].w||dep[y])continue;
dep[y]=dep[x]+1;
if(y==t)return 1;
q.push(y);
}
}
return 0;
}
int dinic(int x,int flow){
int rest=0,k;
if(x==t)return flow;
for(int i=ls[x];i;i=a[i].next){
int y=a[i].to;
if(!a[i].w||dep[y]!=dep[x]+1)continue;
rest+=(k=dinic(y,min(flow-rest,a[i].w)));
a[i].w-=k;a[i^1].w+=k;
if(rest==flow)return flow;
}
if(!rest)dep[x]=0;
return rest;
}
void net_work(){
while(bfs())
ans-=dinic(s,inf);
}
int main()
{
scanf("%d%d%d",&n,&m,&d);
s=p(n,m,0)+1;t=s+1;
for(int i=1;i<=n;i++){
scanf("%s",str+1);
for(int j=1;j<=m;j++){
addl(p(i,j,0),p(i,j,1),str[j]-'0');
connect(i,j);
}
}
for(int i=1;i<=n;i++){
scanf("%s",str+1);
for(int j=1;j<=m;j++){
if(str[j]=='L')addl(s,p(i,j,0),1),ans++;
if(i<=d||j<=d||n-i<d||m-j<d)
addl(p(i,j,1),t,inf);
}
}
net_work();
printf("%d",ans);
}