zoukankan      html  css  js  c++  java
  • POJ 3057 Evacuation(二分图匹配+BFS)

    【题目链接】 http://poj.org/problem?id=3057

    【题目大意】

      给出一个迷宫,D表示门,.表示人,X表示不可通行,
      每个门每时间单位只允许一个人通过,
      每个人移动一格的为一时间单位的时间,
      问所有人逃离这个迷宫的最小时间

    【题解】

      我们首先对于每个门进行搜索,求出其到每个人的最短时间,
      之后我们将每扇门对于人来拆点,分别为这个人第几秒通过这个门
      将拆点后的门对所有人做一遍顺序二分图匹配
      匹配最终完成的时间的门是其第几个拆点那么时间就是第几秒

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <vector> 
    #include <queue>
    using namespace std;
    const int MAX_V=10000;
    int V,match[MAX_V];
    vector<int> G[MAX_V];
    bool used[MAX_V];
    void add_edge(int u,int v){
        G[u].push_back(v);
        G[v].push_back(u);
    }
    bool dfs(int v){
        used[v]=1;
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i],w=match[u];
            if(w<0||!used[w]&&dfs(w)){
                match[v]=u;
                match[u]=v;
                return 1;
            }
        }return 0;
    }
    const int dx[4]={-1,0,0,1},dy[4]={0,-1,1,0};
    const int MAX_X=12,MAX_Y=12;
    int X,Y;
    char field[MAX_X][MAX_X+1];
    vector<int> dX,dY;
    vector<int> pX,pY;
    int dist[MAX_X][MAX_Y][MAX_X][MAX_Y];
    void bfs(int x,int y,int d[MAX_X][MAX_Y]){
        queue<int> qx,qy;
        d[x][y]=0;
        qx.push(x);
        qy.push(y);
        while(!qx.empty()){
            x=qx.front(); qx.pop();
            y=qy.front(); qy.pop();
            for(int k=0;k<4;k++){
                int x2=x+dx[k],y2=y+dy[k];
                if(0<=x2&&x2<X&&0<=y2&&y2<Y&&field[x2][y2]=='.'&&d[x2][y2]<0){
                    d[x2][y2]=d[x][y]+1;
                    qx.push(x2);
                    qy.push(y2);
                }
            }
        }
    }
    void solve(){
        int n=X*Y; 
        dX.clear(); dY.clear();
        pX.clear(); pY.clear();
        memset(dist,-1,sizeof(dist));
        for(int x=0;x<X;x++){
            for(int y=0;y<Y;y++){
                if(field[x][y]=='D'){
                    dX.push_back(x);
                    dY.push_back(y);
                    bfs(x,y,dist[x][y]);
                }else if(field[x][y]=='.'){
                    pX.push_back(x);
                    pY.push_back(y);
                }
            }
        }
        int d=dX.size(),p=pX.size();
        for(int i=0;i<=n*d+p;i++)G[i].clear();
        for(int i=0;i<d;i++){
            for(int j=0;j<p;j++){
                if(dist[dX[i]][dY[i]][pX[j]][pY[j]]>=0){
                    for(int k=dist[dX[i]][dY[i]][pX[j]][pY[j]];k<=n;k++){
                       add_edge((k-1)*d+i,n*d+j);
                    }
                }
            }
        }
        if(p==0){
            puts("0");
            return;
        }
        int num=0;
        memset(match,-1,sizeof(match));
        for(int v=0;v<n*d;v++){
            memset(used,0,sizeof(used));
            if(dfs(v)){
                if(++num==p){
                    printf("%d
    ",v/d+1);
                    return;
                }
            }
        }puts("impossible");
    }
    int T;
    void init(){
        scanf("%d%d",&X,&Y);
        for(int i=0;i<X;i++)scanf("%s",field[i]);
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            init();
            solve();
        }return 0;
    }
  • 相关阅读:
    tp5最强分页 自定义model,控制器引用。只显示一页
    tp5分页,一看就懂,简单明了(附带额外参数)
    PHP 验证5-20位数字加字母的正则(数字和字母缺一不可)!!!
    表格样式
    tp5中很牛皮的一句sql语句,三个条件(两个不确定条件,一个硬性条件)
    centos6.8下搭建git和gitlab版本库
    解决 nginx: [alert] kill(1022, 1) failed (3: No such process)
    Zabbix利用msmtp+mutt发送邮件报警
    nginx基本配置与参数说明
    Linux添加/删除用户和用户组
  • 原文地址:https://www.cnblogs.com/forever97/p/poj3057.html
Copyright © 2011-2022 走看看