• bzoj1189 [HNOI2007]紧急疏散evacuate


    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
    ",L);
        else puts("impossible");
        return 0;
    }
  • 相关阅读:
    JavaScript:事件
    JavaScript系统对象
    DOM基础:table(表格)
    DOM基础
    Cookie的简单实用
    javascript:变量的作用域
    javascript:没有定义的变量和没有定义的属性
    数组的基本使用
    静态代码块、代码块、构造函数、匿名内部类、匿名内部类中的代码块
    java使用指定的国际化文件
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5397044.html
Copyright © 2020-2023  润新知