##题目大意:
在一个行列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。
每行每列中相邻石柱的距离为,蜥蜴的跳跃距离是,即蜥蜴可以跳到平面距离不超过的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。
##思路:
很明显的最大流问题。为了满足一个石柱最多跳只蜥蜴,就要将每个石柱进行拆点,中间流量为,这样就保证了最多只有只蜥蜴可以跳这个石柱。那么这个建图就很明显了:
- 将源点向每个有蜥蜴的柱子连边,边权为1。
- 将与边界距离不足的柱子与汇点连边,边权为。
- 将拆好的柱子两两连边,边权为。
- 将直线距离不大于的柱子连边,边权为。
跑一边最大流即可得到能逃出的蜥蜴数量,再用总蜥蜴数量减去得到的答案即可。
##代码:
#include <cstdio>
#include <iostream>
#include <queue>
#include <cstring>
#define Inf 0x7f
#define INF 1e9
using namespace std;
int n,m,d,a[41][41],head[500001],dep[500001],s,t,k,ans,num,sum,x,y;
char c;
struct edge
{
int next,to,c;
}e[500001];
void add(int from,int to,int c)
{
k++;
e[k].c=c;
e[k].to=to;
e[k].next=head[from];
head[from]=k;
}
bool check(int x1,int y1,int x2,int y2)
{
return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)<=d*d);
//计算两个柱子的直线距离
//两边同时开方得 sqrt((x1-x2)^2+(y1-y2)^2)<=d
//再利用毕达哥拉斯定理计算
}
bool bfs() //分层
{
queue<int> q;
q.push(s);
memset(dep,Inf,sizeof(dep));
dep[s]=0;
while (q.size())
{
int u=q.front();
q.pop();
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (dep[v]>dep[u]+1&&e[i].c)
{
dep[v]=dep[u]+1;
q.push(v);
}
}
}
return (dep[t]<Inf);
}
int dfs(int u,int low)
{
int lows=0;
if (u==t) return low;
for (int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (dep[v]==dep[u]+1&&e[i].c)
{
lows=dfs(v,min(low,e[i].c));
if (!lows) continue;
e[i].c-=lows; //正向边
e[(i+1)^1-1].c+=lows; //反向边
return lows;
}
}
return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&d);
s=0;
t=n*m*2+1;
//柱子a编号为1~n*m,柱子b编号为n*m+1~2*n*m
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%1d",&a[i][j]);
x=(i-1)*m+j; //计算编号
add(x,x+n*m,a[i][j]);
add(x+n*m,x,0); //柱子a和柱子b连接
if (i-d<1||i+d>n||j-d<1||j+d>m) //能跳到边界外
{
add(x+n*m,t,INF);
add(t,x+n*m,0); //与t相连
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
cin>>c;
if (c=='L') //蜥蜴
{
num++;
x=(i-1)*m+j;
add(s,x,1);
add(x,s,0); //与s相连
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
for (int k=1;k<=n;k++)
for (int l=1;l<=m;l++)
if (check(i,j,k,l)) //距离不大于d
{
x=(i-1)*m+j;
y=(k-1)*m+l;
add(x+n*m,y,INF);
add(y,x+n*m,0);
add(y+n*m,x,INF);
add(x,y+n*m,0);
}
while (bfs())
{
while (sum=dfs(s,INF))
ans+=sum;
}
printf("%d\n",num-ans);
return 0;
}