bzoj 1066トカゲ

7415 ワード

Description
r行c列のグリッドマップには高さの異なる石柱があり、いくつかの石柱にはトカゲが立っています.あなたの任務はできるだけ多くのトカゲを境界の外に逃がすことです.各行の各列の隣接する石柱の距離は1であり、トカゲのジャンプ距離はdであり、すなわちトカゲは平面距離がdを超えないいずれかの石柱にジャンプすることができる.石柱は不安定で、トカゲがジャンプするたびに離れた石柱の高さが1(地図の内部に落ちている場合は到達した石柱の高さが変わらない)減少し、その石柱の元の高さが1であればトカゲは離れて消えてしまう.その後他のトカゲは足を踏み入れることができない.いつでも2匹のトカゲが同じ石柱にいることはできない.
Input
第1の挙動の3つの整数r,c,d,すなわち地図の規模と最大ジャンプ距離を入力する.以下rは石竹の初期状態を示し、0は石柱がないことを示し、1~3は石柱の初期高さを示す.以下rはトカゲの位置を表し、「L」はトカゲを表す.トカゲがいないことを示す.
Output
出力は1行のみで、脱出できないトカゲの総数の最小値を含む整数です.
さいだいりゅう
各石柱は2つの点に分解され、連辺容量は石柱の高さである.
距離dを超えない石柱間で辺をつなぎ、容量はinf
ソースポイントの端からトカゲのある石柱まで、容量は1です.
図外にジャンプ可能な点連辺から汇点まで、容量はinf
#include<cstdio>
#include<cstring>
struct edge{
    int nx,w;
    edge(){}
    edge(int a,int b){
        nx=a;
        w=b;
    }
}es[100005];
int ep=2;
const int S=0,T=1,INF=2147483647;
int g[100005][2],gp=1005;
int h[10005];
int v[105][105];
int q[10005];
int n,m,ans=0,mx,ls=0;
int ids[24][24],idp=2;
int hs[24][24];
char c;
inline int min(int a,int b){return a<b?a:b;}
inline void addedge(int s,int t,int w){
    es[ep]=edge(t,w);
    g[gp][0]=ep++;
    g[gp][1]=g[s][1];
    g[s][1]=gp++;
    es[ep]=edge(s,0);
    g[gp][0]=ep++;
    g[gp][1]=g[t][1];
    g[t][1]=gp++;
}
inline bool bfs(){
    int qs=0,qe=0;
    q[qe++]=S;
    memset(h,-1,sizeof h);
    h[S]=0;
    while(qs<qe){
        int w=q[qs++];
        int i=w;
        while(i=g[i][1]){
            int e=g[i][0];
            int u=es[e].nx;
            if(h[u]!=-1||!es[e].w)continue;
            h[u]=h[w]+1;
            q[qe++]=u;
        }
    }
    return h[T]!=-1;
}
int dfs(int w,int f){
    if(w==T)return f;
    int i=w;
    int used=0,c;
    while(i=g[i][1]){
        int e=g[i][0];
        int u=es[e].nx;
        if(h[u]!=h[w]+1||es[e].w==0)continue;
        c=f-used;
        c=dfs(u,min(c,es[e].w));
        es[e].w-=c;
        es[e^1].w+=c;
        used+=c;
        if(used==f)return f;
    }
    if(!used)h[w]=-1;
    return used;
}
char gc(){
    char c=getchar();
    while((c<'0'||c>'9')&&c!='L'&&c!='.')c=getchar();
    return c;
}
int main(){
    scanf("%d%d%d",&n,&m,&mx);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            ids[i][j]=idp++;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            c=gc();
            hs[i][j]=c-'0';
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(hs[i][j]>0){
                addedge(ids[i][j],ids[i][j]+n*m,hs[i][j]);
                bool o=0;
                for(int x=-mx;x<=mx;x++){
                    for(int y=-mx;y<=mx;y++){
                        if(x*x+y*y>mx*mx)continue;
                        if(i+x<0||i+x>=n||j+y<0||j+y>=m){
                            o=1;
                            continue;
                        }
                        if(hs[i+x][j+y]==0)continue;
                        addedge(ids[i][j]+n*m,ids[i+x][j+y],INF);
                    }
                }
                if(o)addedge(ids[i][j]+n*m,T,INF);
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            c=gc();
            if(c=='L')addedge(S,ids[i][j],1),ls++;
        }
    }
    while(bfs())ans+=dfs(S,INF);
    printf("%d",ls-ans);
    return 0;
}