ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

Description

发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

Input

输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

Output

只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出'impossible'(不包括引号)。

 二分答案,对答案ans,把每个门拆成ans个点表示每个时刻,每个人到能在规定时间内到达的门连边,得到二分图,若最大匹配为人数则为可行解

#include<cstdio>
const int M=4000000,inf=0x3f3f3f3f;
int h[M],q[M],S,T;
int es[M],enx[M],ev[M],e0[M],ep=2;
int n,m;
char s[64][64];
bool bfs(){
    int ql=0,qr=0;
    for(int i=1;i<=T;i++)h[i]=0;
    h[S]=1;
    q[qr++]=S;
    while(ql!=qr){
        int w=q[ql++];
        for(int i=e0[w];i;i=enx[i]){
            if(!ev[i])continue;
            int u=es[i];
            if(h[u])continue;
            h[u]=h[w]+1;
            q[qr++]=u;
        }
    }
    return h[T];
}
int dfs(int w,int f){
    if(w==T)return f;
    int used=0,c;
    for(int i=e0[w];i;i=enx[i]){
        if(!ev[i])continue;
        int u=es[i];
        if(h[u]!=h[w]+1)continue;
        c=f-used;
        if(c>ev[i])c=ev[i];
        c=dfs(u,c);
        ev[i]-=c;
        ev[i^1]+=c;
        used+=c;
        if(f==used)return f;
    }
    if(f!=used)h[w]=0;
    return used;
}
void addedge(int a,int b,int f){
    es[ep]=b;enx[ep]=e0[a];ev[ep]=f;e0[a]=ep++;
    es[ep]=a;enx[ep]=e0[b];ev[ep]=0;e0[b]=ep++;
}
int xs[]={-1,0,1,0};
int ys[]={0,-1,0,1};
int qx[10000],qy[10000],tag[64][64],len[64][64],now=0;
bool chk(int X){
    int pc=0;
    S=(n+2)*m+2+X*n*m;T=S+1;
    for(int i=0;i<=T;i++)e0[i]=0;ep=2;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(s[i][j]=='.')addedge(S,i*m+j,1),pc++;
            if(s[i][j]=='D'){
                for(int c=0;c<=X;c++)addedge(i*m+j+c*n*m,T,1);
                int ql=0,qr=0;
                qx[0]=i;qy[0]=j;qr++;
                ++now;
                tag[i][j]=now;
                len[i][j]=0;
                while(ql<qr){
                    int x=qx[ql],y=qy[ql];ql++;
                    if(s[x][y]=='.'&&len[x][y]<=X)for(int c=len[x][y];c<=X;c++)addedge(x*m+y,i*m+j+c*n*m,1);
                    if(len[x][y]<=X)
                    for(int a=0;a<4;a++){
                        int x1=x+xs[a],y1=y+ys[a];
                        if((s[x1][y1]=='.')&&tag[x1][y1]!=now){
                            tag[x1][y1]=now;
                            len[x1][y1]=len[x][y]+1;
                            qx[qr]=x1;qy[qr]=y1;qr++;
                        }
                    }
                }
            }
        }
    }
    while(bfs())pc-=dfs(S,inf);
    return !pc;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<=51;i++)for(int j=0;j<=51;j++)s[i][j]='X';
    for(int i=1;i<=n;i++){
        scanf("%s",s[i]+1);
        s[i][m+1]='X';
    }
    int L=0,R=n*m+1,M;
    while(L<R){
        M=L+R>>1;
        if(chk(M))R=M;
        else L=M+1;
    }
    while(!chk(L)&&L<=n*m)++L;
    while(L>0&&chk(L-1))--L;
    if(L<=n*m)printf("%d\n",L);
    else puts("impossible");
    return 0;
}

 

posted on 2016-04-15 21:46  nul  阅读(411)  评论(0编辑  收藏  举报