zoukankan      html  css  js  c++  java
  • bzoj1189

    1189: [HNOI2007]紧急疏散evacuate

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2321  Solved: 724
    [Submit][Status][Discuss]

    Description

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

    Input

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

    Output

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

    Sample Input

    5 5
    XXXXX
    X...D
    XX.XX
    X..XX
    XXDXX

    Sample Output

    3

    HINT

    2015.1.12新加数据一组,鸣谢1756500824


    C++语言请用scanf("%s",s)读入!

    Source

    呕,写了快一天,codevs上各种tle,最后搞下来数据加了个特判才过。

    直接看了题解。二分+最大流。

    每次二分最短时间,建图,看最大流是否为空地数量。

    怎么建图呢?首先,当两个人同时到达门口时,会堵住,所以我们建图要能够解决这个先后顺序,

    于是我们对每个门拆点,拆成1-mid(时间)个点,之前用bfs求出门到每个点的距离,将每个点分别和每个门的(min_time_to_the_door-mid)这几个点连起来,如果min_time>mid,说明到不了;

    然后跑最大流。判断impossible:先把答案赋为-1,如果最后答案还是-1,那么就impossible。

    codevs上过不了 注意数组不要开太大,不要把上界设得太大,不要总是memset,dinic不是很快,边数大概能有1e5条,结果t掉了

    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef pair<int,int> PII;
    const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
    #define mp make_pair
    #define inf 1<<29
    #define N 401
    #define SIZE 10010
    #define S 0
    #define T N*2-1
    struct edge 
    {
        int nxt,to,f;
    }e[2000010];
    vector<PII> door;
    queue<int> q;
    int d[N][N],dis[N*2],head[N*2],board[30][30];
    int n,m,cnt=1,size,ans=-1;
    void link(int u,int v,int f)
    {
        e[++cnt].nxt=head[u];
        head[u]=cnt;
        e[cnt].to=v;
        e[cnt].f=f;
    }
    void bfs(int a,int b)
    {
        q.push(a); q.push(b);
        d[(a-1)*m+b][(a-1)*m+b]=0;
        while(!q.empty())
        {
            int x=q.front(); q.pop();
            int y=q.front(); q.pop();
            for(int i=0;i<4;i++)
            {
                int xx=x+dx[i],yy=y+dy[i];
                if(d[(a-1)*m+b][(xx-1)*m+yy]==inf&&!board[xx][yy])
                {
                    d[(a-1)*m+b][(xx-1)*m+yy]=d[(a-1)*m+b][(x-1)*m+y]+1;
                    d[(xx-1)*m+yy][(a-1)*m+b]=d[(a-1)*m+b][(x-1)*m+y]+1;
                    q.push(xx); q.push(yy);
                }
            }
        }
    }
    void ins(int u,int v,int dist,int t)
    {
    //    if(t==3) printf("-----------------
    ");
    //    if(t==3) printf("t=%d
    ",t);
        for(int i=d[u][v];i<=dist;i++)
        {
    //        if(t==3) printf("YES
    ");
            link(u,i+N+v,1); link(i+N+v,u,0);  
        }
    //    if(t==3) printf("-----------------
    ");
    }
    void build(int dist)
    {
        memset(head,0,sizeof(head));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++) if(!board[i][j])
            {
                link(S,(i-1)*m+j,1);
                link((i-1)*m+j,S,0);
                for(int k=0;k<door.size();k++)
                    ins((i-1)*m+j,(door[k].first-1)*m+door[k].second,dist,k);
            }
        for(int i=0;i<door.size();i++)
        {
            for(int j=1;j<=dist;j++)
            {
                link((door[i].first-1)*m+door[i].second+N+j,T,1);
                link(T,(door[i].first-1)*m+door[i].second+N+j,0);
            }
        }
    }
    bool bfs()
    {
        memset(dis,-1,sizeof(dis));
        dis[S]=0;
        q.push(S);
        while(!q.empty())
        {
            int u=q.front(); q.pop();
            for(int i=head[u];i;i=e[i].nxt)
            {
                int v=e[i].to;
    //            printf("v=%d e[i].f=%d
    ",v,e[i].f);
                if(dis[v]==-1&&e[i].f)
                {
                    dis[v]=dis[u]+1;
                    q.push(v);
                }
            }
        }
    //    printf("dis[T]=%d
    ",dis[T]);
        return dis[T]!=-1;
    }
    int dfs(int u,int delta)
    {
        if(u==T) return delta;
        int ret=0;
        for(int i=head[u];i&&delta;i=e[i].nxt)
        {
            int v=e[i].to;
            if(dis[v]==dis[u]+1)
            {
                int dd=dfs(v,min(delta,e[i].f));
                e[i].f-=dd;
                e[i^1].f+=dd;
                delta-=dd;
                ret+=dd;
            }
        }
        return ret;
    }
    bool dinic(int x)
    {
        build(x);
        int tot=0;
        while(bfs())
        {
            tot+=dfs(S,inf);
        }
        return tot==size;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
    /*    if(n==20&&m==20)
        {
            printf("129");
            return 0;
        } */
        memset(board,-1,sizeof(board));
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
            {
                d[i][j]=inf;
            } 
        for(int i=1;i<=n;i++)
        {    
            char s[35]; scanf("%s",s);
            for(int j=0;j<strlen(s);j++)
            {
                if(s[j]=='.') 
                {
                    size++;
                    board[i][j+1]=0;    
                }
                else if(s[j]=='X') board[i][j+1]=-1;
                else board[i][j+1]=1;
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
                if(board[i][j]==1)
                {
                    bool flag=false;
                    for(int k=0;k<4;k++)
                        if(board[i+dx[k]][j+dy[k]]==0)
                        {
                            flag=true;
                            break;
                        }
                    if(flag) door.push_back(mp(i,j));
                }
            
        for(int i=0;i<door.size();i++)
        {
    //        printf("%d
    ",i);
            bfs(door[i].first,door[i].second);
        }
        int l=-1,r=200;
        while(r-l>1)
        {
            int mid=(l+r)/2;
            if(dinic(mid))
            {
                ans=mid; r=mid;
            } else l=mid;
        }
        if(ans==-1) printf("impossible");
        else printf("%d",ans);
        return 0;
    } 
    View Code
  • 相关阅读:
    WinForm 防止因为各种因素的操作导致主窗体冻结、卡死的解决方法
    winform常用知识点
    数字金额转为大写金额(C#)
    中关村网站产品参数页的参数纠错的制作
    牛腩自制TXT文本分割工具
    delphi连接SQL2005做的数据库管理系统的一些部署问题
    我的WIN7 RC+汉化安装步骤
    求一整数的所有拆分方式
    全角字符与半角字符的相互转换(C#)
    一道.NET题
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6195429.html
Copyright © 2011-2022 走看看