zoukankan      html  css  js  c++  java
  • [bzoj1189] [HNOI2007]紧急疏散evacuate

    来自FallDream的博客,未经允许,请勿转载,谢谢。

    -----------------------------------------------------------------------------

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

    n,m<=20

    看到题目很容易想到二分答案,然后分层图网络流,每一个点都拆成很多个点,每个点向下个时间点能到的点连边,然后check一下是否能全部撤离。想了想没问题,写一发T了。

    但是仔细想想,并不需要那么复杂。因为这道题每个人到每个出口的路径长度确定,所以只需要把每个出口拆点就行了,每个人向每个能到的出口,第(它能到的时间)个点连边,每个出口拆成的点向下一个连边,就行啦。

    代码巨丑...

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #define S 0
    #define T 30000
    #define INF 2000000000
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    int id[22][22],s[405][405];
    int d[T+5],q[T+5],n,m,head[T+5],c[T+5],cnt=1,tot=0,top,num=0;
    struct edge{int to,next,w;}e[T*200];
    char st[22][22];
    struct pos{int x,y;};queue<pos> qu;
    const int dis[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
    
    inline void ins(int f,int t,int w){
        e[++cnt]=(edge){t,head[f],w};head[f]=cnt;
        e[++cnt]=(edge){f,head[t],0};head[t]=cnt;
    }
    
    int dfs(int x,int f)
    {
        if(x==T)return f;
        int used=0;
        for(int&i=c[x];i;i=e[i].next)
            if(e[i].w&&d[e[i].to]==d[x]+1)
            {
                int w=dfs(e[i].to,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(used==f)return f;
            }
        return d[x]=-1,used;
    }
    
    bool bfs()
    {
        int i,j;memset(d,0,sizeof(d));
        for(d[q[top=i=1]=S]=1;i<=top;i++)
            for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)
                if(e[j].w&&!d[e[j].to])
                    d[q[++top]=e[j].to]=d[q[i]]+1;
        return d[T];
    }
    
    void build(int x)
    {
        cnt=1;memset(head,0,sizeof(head));
        for(int i=1;i<=num;i++)
        {
            for(int k=1;k<=x;k++)
                ins((k-1)*num+i,T,1);
            for(int k=1;k<x;k++)
                ins((k-1)*num+i,k*num+i,INF);
        }
        for(int i=num+1;i<=tot;i++)
        {
            ins(S,num*x+i,1);
            for(int j=1;j<=num;j++)
                if(s[i][j]<=x)
                    ins(num*x+i,(s[i][j]-1)*num+j,INF);
        }
    }
    
    void getdis(int x,int y)
    {
        int now=id[x][y];qu.push((pos){x,y});
        s[now][now]=0;
        while(!qu.empty())
        {
            pos th=qu.front();qu.pop();
            for(int i=0;i<4;i++)
            {
                int xx=th.x+dis[i][0],yy=th.y+dis[i][1];
                if(xx<1||yy<1||xx>n||yy>m||s[xx][yy]=='X') continue;
                if(s[now][id[th.x][th.y]]+1<s[now][id[xx][yy]])
                {
                    s[now][id[xx][yy]]=s[now][id[th.x][th.y]]+1;
                    if(st[xx][yy]=='.')qu.push((pos){xx,yy});
                }
            }
        }
    }
    
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)
            scanf("%s",st[i]+1);
        memset(s,127,sizeof(s));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(st[i][j]=='D')id[i][j]=++num;
        tot=num;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(st[i][j]=='.')
                    id[i][j]=++tot;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(st[i][j]=='.')
                    getdis(i,j);
        int l=1,r=324,mid,ans=-1;
        while(l<=r)
        {
            mid=l+r>>1;build(mid);
            int sum=0;
            while(bfs())sum+=dfs(S,INF);
            if(sum==tot-num)ans=mid,r=mid-1;
            else l=mid+1;
        }
        if(ans==-1)return 0*puts("impossible");
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    数据库一直显示恢复中。。记录一则处理数据库异常的解决方法
    MSSQl分布式查询
    ASP.NET MVC中实现数据库填充的下拉列表 .
    理解浮点数的储存规则
    获取 "斐波那契数列" 的函数
    Int64 与 Currency
    学 Win32 汇编[33] 探讨 Win32 汇编的模块化编程
    学 Win32 汇编[34] 宏汇编(1)
    Delphi 中 "位" 的使用(2) 集合
    如何用弹出窗口显示进度 回复 "嘿嘿嘿" 的问题
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj1189.html
Copyright © 2011-2022 走看看