题目分享L 二代目

题意:有一个X*Y的房间,‘X’代表墙壁,‘D’是门,‘.’代表人。这个房间着火了,人要跑出去,但是每一个时间点只有一个人可以从门出去。
问最后一个人逃出去的最短时间,如果不能逃出去,输出impossible。

分析:因为每个时刻每扇门只能有一个人通过,所以联想到二分图

一边应该是p个人的位置,另一边应该是n*m个每个时刻的d扇门

因为只要找到每个人到达每扇门的最短距离所需花费的时间

其以后的所有时刻都是可以到达的

所以要把每个人与每扇门直接最短时间及其以后全部连边,因为最长也就是n*m秒,所以连到n*m即可

这里我就卡了很久因为不知道如何求p个人到d扇门的距离

开始用了各种map之类

后来看了题解才发现只需要一遍bfs求出每扇门到达n*m所有节点的距离,然后mapp[i][p[j].x][p[j].y]其实就是dis[i][j]了

代码稍微有一点不好写

不过看肯定能看明白

扫描二维码关注公众号,回复: 11199885 查看本文章
void chuli()
{
    int d_cnt=d.size(),p_cnt=p.size(),ans=0;;
    memset(girl,-1,sizeof(girl));
    for(int i=0;i<n*m*d_cnt;i++)
    {
        memset(vis,0,sizeof(vis));
        ans+=dfs(i);
        if(ans==p_cnt)
        {
            printf("%d\n",i/d_cnt+1);
            return;
        }
    }
    printf("impossible\n");
    return ;
}

这里可能会稍微有点疑问

为什么要写i/d_cnt+1之类的

其实我们门那边的节点是这样的

d0t0(0号门,第0时刻)d1t0,d2t0...dnt0,d1t1,d1t2...

而众所周知,这题是求最大匹配,那么如果我们用了前i个就可以使所有人都逃出来,那么肯定就不需要用后面的了

那么显然,第i个点对应的时间就是i/d_cnt+1

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;

const int maxn=2e1+1;
const int maxm=3e4+1;

struct Node
{
    int x,y;
    Node(){}
    Node(int X,int Y){x=X,y=Y;}
};

int mapp[maxm][maxn][maxn];
int xx[4]={0,1,0,-1};
int yy[4]={1,0,-1,0};
char a[maxn][maxn];
vector<Node> p;
vector<Node> d;
vector<int> e[maxm];
int girl[maxm];
bool vis[maxm];
int n,m;

int dfs(int x)
{
    for(int i=0;i<e[x].size();i++)
    {
        int v=e[x][i];
        if(!vis[v])
        {  
            vis[v]=1;
            if(girl[v]==-1||dfs(girl[v]))
            {
                girl[v]=x;
                return 1;
            }
        }
    }
    return 0;
}

void bfs(int x,int dis[maxn][maxn])
{
    queue<Node> q;
    dis[d[x].x][d[x].y]=0;
    q.push(d[x]);
    while(!q.empty())
    {
        Node now=q.front();q.pop();
        for(int i=0;i<4;i++)
        {
            int nowx=xx[i]+now.x,nowy=yy[i]+now.y;
            if(nowx>=0&&nowx<n&&nowy>=0&&nowy<m&&a[nowx][nowy]=='.'&&dis[nowx][nowy]==-1)
            {
                dis[nowx][nowy]=dis[now.x][now.y]+1;
                q.push(Node(nowx,nowy));
            }
        }
    }
}

void chuli()
{
    int d_cnt=d.size(),p_cnt=p.size(),ans=0;;
    memset(girl,-1,sizeof(girl));
    for(int i=0;i<n*m*d_cnt;i++)
    {
        memset(vis,0,sizeof(vis));
        ans+=dfs(i);
        if(ans==p_cnt)
        {
            printf("%d\n",i/d_cnt+1);
            return;
        }
    }
    printf("impossible\n");
    return ;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        d.clear();p.clear();
        for(int i=0;i<n;i++)
        {
            char ch=getchar();
            for(int j=0;j<m;j++)
            {
                a[i][j]=getchar();
                if(a[i][j]=='D') d.push_back(Node(i,j));
                else if(a[i][j]=='.') p.push_back(Node(i,j));
            }
        }
        int d_cnt=d.size(),p_cnt=p.size();
        if(!p_cnt)
        {
            printf("0\n");
            continue;
        }
        memset(mapp,-1,sizeof(mapp));
        for(int i=0;i<d_cnt;i++) bfs(i,mapp[i]);
        for(int i=0;i<n*m*d_cnt;i++) e[i].clear();
        for(int i=0;i<d_cnt;i++)
            for(int j=0;j<p_cnt;j++)
                if(mapp[i][p[j].x][p[j].y]!=-1)
                    for(int k=mapp[i][p[j].x][p[j].y];k<=n*m;k++)
                        e[(k-1)*d_cnt+i].push_back(j);
        chuli();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lin4xu/p/12896653.html
今日推荐