易水人去,明月如霜。
Description
在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃
到边界外。 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石
柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不
变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个
石柱上。
Input
输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱
,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。
Output
输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。
Sample Input
00000000
02000000
00321100
02000000
00000000
........
........
..LLLL..
........
........
Sample Output
HINT
100%的数据满足:1<=r, c<=20, 1<=d<=4
思路:经典的网络流题目,思考柱子高度的模型,我们可以将高度等价为,有该高度只蜥蜴可在这个柱子上跳,这样问题就变得明了啦,对于每个石柱,我们把它拆成2个点,称为入点和出点,入点和出点连一条边,容量为高度,如果A石柱能跳到B石柱,就把出点A和入点B连一条边,容量为无限,这条边模拟的是跳的过程。如果该石柱能跳出去,就在该石柱出点和汇点T连一条边,容量无限。这条边模拟跳出去的过程。 如果该石柱有蜥蜴,在源点S和该石柱入点连一条边,容量为1.
这样的话,每个有蜥蜴的石柱上都有一只蜥蜴,如果该蜥蜴想从该石柱跳开,必定要先从该石柱入点跑到该石柱出点,这样会消耗1的容量,然后跳出去后,跳到另一石柱时,想再跳的话,又会消耗那个石柱的容量 ,直到跳到汇点T,贡献了1的流量。所以这幅图的最大流表示的就是能逃脱的蜥蜴数量,输出答案时减一下就行了。
代码:
#include<stdio.h>
#include<cstring>
#include<iostream>
const int INF=999999;
char c,u,a[21][21];
int map[1002][1002],fin[21][21],n,m,d,cnt,ant,ans,i,j,x[20001],pre[1001];
using namespace std;
void make_picture(int x,int y)
{
int now=fin[x][y]+1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if ((i!=x||j!=y)&&(a[i][j]>'0'))
{
if (d*d>=(x-i)*(x-i)+(y-j)*(y-j))
map[now][fin[i][j]]=INF;
}
}
void go_down()
{
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (i-d<1||i+d>n||j-d<1||j+d>m)
{
int now=fin[i][j]+1;
map[now][cnt]=INF;
}
}
void flow()
{
while (true)
{
int h=0,t=1;x[1]=0;
memset(pre,-1,sizeof(pre));
while (h<t)
{
int now=x[++h];
for (int i=1;i<=cnt;i++)
if (pre[i]<0&&map[now][i]>0)
{
x[++t]=i;pre[i]=now;
}
if (pre[cnt]>0) break;
}
if (pre[cnt]<0) break;int small=INF;
for (i=cnt;i!=0;i=pre[i]) small=min(map[pre[i]][i],small);
for (i=cnt;i!=0;i=pre[i]) {map[pre[i]][i]-=small;map[i][pre[i]]+=small;}
ans+=small;
}
}
int main()
{
scanf("%ld%ld%ld",&n,&m,&d);
scanf("%c",&u);cnt=0;
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
scanf("%c",&a[i][j]);
if (a[i][j]!='0')
{
cnt++;fin[i][j]=cnt;
map[cnt][cnt+1]=a[i][j]-48;cnt++;
}
}
scanf("%c",&u);
}
for (i=1;i<=n;i++)
{
for (j=1;j<=m;j++)
{
scanf("%c",&c);
if (c=='L') {ant++;map[0][fin[i][j]]=1;}
if (a[i][j]>'0') {make_picture(i,j);}
}
scanf("%c",&u);
}
cnt++;go_down();
flow();
printf("%d",ant-ans);
return 0;
}