正题
题目链接:https://www.luogu.com.cn/problem/P2472
题目大意
n∗mn*mn∗m个格子,每个格子的石柱高度不同,蜥蜴可以跳到距离不超过ddd的石柱处,并且先前所站的石柱高度减一,为0则不能站,然后求有多少只蜥蜴不可以逃脱。
解题思路
考虑网络流,每只蜥蜴表示一个流,将每个石柱分成入点和出点,然后入点连出点流量为石柱高度,然后每个可以走的点之间出点连入点无限,之后有蜥蜴的柱子原点连入点流量为1,可以逃脱的出点连汇点。
然后dinic即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#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);
}