POJ 3057-Evacuation

分析

这个题想了半天。
最开始想的是不断地BFS,但这样不仅时间复杂度没有保障,而且正确性可能也有问题。
如果门是固定的,还可以考虑像曾经一个题那么做,但现在不行了,因为门不仅不固定,而且还有很多个。
但有一个性质可以考虑,就是每扇门在某一时刻只能走出一个人。
不难想到二分图匹配。

#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=15,M=1e5+10;
struct Node{
    int x,y;
    Node(){}
    Node(int a,int b){
        x=a;y=b;
    }
};
struct Edge{
    int to,nxt;
}e[M*100];
int h[10*M],idx;
void Ins(int a,int b){
    e[++idx].to=b;e[idx].nxt=h[a];h[a]=idx;
}
char map[N][N],vis[M];
int match[M*10],dis[N][N],d[N][N][N][N],n,m;
vector <Node > pi,di;
void bfs(int x,int y){
    int dx[]={1,-1,0,0};
    int dy[]={0,0,1,-1};
    memset(dis,-1,sizeof(dis));
    dis[x][y]=0;
    queue<Node > q;
    q.push(Node(x,y));
    while(!q.empty()){
        Node u=q.front();q.pop();
        for(int i=0;i<4;i++){
            int ux=u.x+dx[i];
            int uy=u.y+dy[i];
            if(ux>=0&&uy>=0&&ux<n&&uy<m){
                if(map[ux][uy]=='.'&&dis[ux][uy]==-1){
                    dis[ux][uy]=dis[u.x][u.y]+1;
                    d[x][y][ux][uy]=dis[ux][uy];
                    q.push(Node(ux,uy));
                }
            }
        }
    }
}
bool dfs(int x){
    vis[x]=1;
    for(int i=h[x];i;i=e[i].nxt){
        int v=e[i].to;
        if(match[v]==-1||!vis[match[v]]&&dfs(match[v])){
            match[v]=x;
            match[x]=v;
            return 1;
        }
    }
    return 0;
}
int sum(int x){
    for(int i=0;i<pi.size();i++)
        for(int j=0;j<di.size();j++){
            int px=pi[i].x,py=pi[i].y;
            int dx=di[j].x,dy=di[j].y;
            if(d[dx][dy][px][py]<=x){
                Ins(x*di.size()+j,(n*m+10)*di.size()+10+i);
                Ins((n*m+10)*di.size()+10+i,x*di.size()+j);
            }
        }
    int tot=0;
    for(int i=0;i<di.size();i++){
        int u=i+x*di.size();
        if(match[u]==-1){
            memset(vis,0,sizeof(vis));
            if(dfs(u))tot++;
        }
    }
    return tot;
}
void calc(){
    memset(match,-1,sizeof(match));
    int tot=0;
    for(int i=0;i<=m*n+3;i++){
        tot+=sum(i);
        if(tot>=pi.size()){
            printf("%d\n",i);
            return ;
        }
    }
    printf("impossible\n");
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        idx=0;
        pi.clear();di.clear();
        memset(d,0x3f,sizeof(d));
        memset(h,0,sizeof(h));
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
            scanf("%s",map[i]);
        for(int i=0;i<n;i++){
            for(int j=0;j<m;j++){
                if(map[i][j]=='D'){
                    di.push_back(Node(i,j));
                    bfs(i,j);                    
                }else if(map[i][j]=='.'){
                    pi.push_back(Node(i,j));
                }
            }
        }
        calc();
    }
}
posted @ 2020-05-16 10:50  An_Fly  阅读(201)  评论(0编辑  收藏  举报