描述

  在一个r行c列的网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外。

  每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴可以跳到平面距离不超过d的任何一个石柱上。石柱都不稳定,每次当蜥蜴跳跃时,所离开的石柱高度减1(如果仍然落在地图内部,则到达的石柱高度不变),如果该石柱原来高度为1,则蜥蜴离开后消失。以后其他蜥蜴不能落脚。任何时刻不能有两只蜥蜴在同一个石柱上。

输入

  输入第一行为三个整数r,c,d,即地图的规模与最大跳跃距离。以下r行为石竹的初始状态,0表示没有石柱,1~3表示石柱的初始高度。以下r行为蜥蜴位置,“L”表示蜥蜴,“.”表示没有蜥蜴。

输出

  输出仅一行,包含一个整数,即无法逃离的蜥蜴总数的最小值。

 

提示

  【限制】 100%的数据满足:1<=r, c<=20, 1<=d<=3

题解

  这是一道网络流。

  先考虑如何建图:对于每根石柱,我们可以把它拆成两个点,中间连一条容量为其高度的边。对于每根石柱,我们再将它和与它距离不超过d的所有石柱连边,容量无限。对于每根能够跳出去的石柱,我们将它与汇点t相连。对于每根有蜥蜴的石柱,我们将源点s与它相连。这样我们就可以跑最大流了。放上代码:

#include<bits/stdc++.h>
using namespace std;
#define N 100010
#define INF 0x3f3f3f3f
int r,c,d;
int num=1,f[N];
struct node{
    int u,v,w,nxt;
}e[N<<1];
void add(int u,int v,int w){
    e[++num]=(node){u,v,w,f[u]};f[u]=num;
    e[++num]=(node){v,u,0,f[v]};f[v]=num;
}
//build graph
int s,t,dis[N];
int bfs(){
    queue<int>q;
    memset(dis,-1,sizeof(dis));
    q.push(s);dis[s]=0;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=f[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(w&&dis[v]==-1){
                dis[v]=dis[u]+1;q.push(v);
                if(v==t) return 1;
            }
        }
    }
    return 0;
}
int dfs(int u,int flow){
    if(u==t||!flow) return flow;
    int ret=0;
    for(int i=f[u];i;i=e[i].nxt){
        int v=e[i].v;
        if(e[i].w&&dis[v]==dis[u]+1){
            int w=dfs(v,min(e[i].w,flow));
            if(!w) continue;
            ret+=w;flow-=w;e[i].w-=w;e[i^1].w+=w;
            if(!flow) break;
        }
    }
    if(!ret) dis[u]=-1;
    return ret;
}
int dinic(){
    int mf=0;
    while(bfs()){mf+=dfs(s,INF);}
    return mf;
}
//flow
int cnt,id[30][30][2],mp[30][30];
char ch[30];
int dist(int xx,int yy){return xx*xx+yy*yy;}
int ID(int i,int j){return (i-1)*c+j;}
int main(){
    scanf("%d%d%d",&r,&c,&d);s=0;t=(r*c)<<1|1;
    for(int i=1;i<=r;i++){
        scanf("%s",ch+1);
        for(int j=1;j<=c;j++){
            mp[i][j]=ch[j]-'0';
            id[i][j][0]=ID(i,j);id[i][j][1]=id[i][j][0]+r*c;
            if(mp[i][j]) add(id[i][j][0],id[i][j][1],mp[i][j]);
        }
    }
    for(int i=1;i<=r;i++){
        scanf("%s",ch+1);
        for(int j=1;j<=c;j++){if(ch[j]=='L') cnt++,add(s,id[i][j][0],1);}
    }
    for(int i=1;i<=r;i++){
        for(int j=1;j<=c;j++){
            if(!mp[i][j]) continue;
            if(i<=d||j<=d||r-i+1<=d||c-j+1<=d) add(id[i][j][1],t,INF);
            for(int dx=-d;dx<=d;dx++){
                int xx=i+dx;
                if(xx<1||xx>r) continue;
                for(int dy=-d;dy<=d;dy++){
                    int yy=j+dy;
                    if(yy<1||yy>c||!mp[xx][yy]||dist(xx-i,yy-j)>d*d) continue;
                    if(xx==i&&yy==j) continue;
                    add(id[i][j][1],id[xx][yy][0],INF);
                }
            }
        }
    }
    printf("%d",cnt-dinic());
    return 0;
}