zoukankan      html  css  js  c++  java
  • 题目分享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]了

    代码稍微有一点不好写

    不过看肯定能看明白

    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
    ",i/d_cnt+1);
                return;
            }
        }
        printf("impossible
    ");
        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
    ",i/d_cnt+1);
                return;
            }
        }
        printf("impossible
    ");
        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
    ");
                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;
    }
  • 相关阅读:
    程序猿之没事瞎吐槽
    iOS 打印日志的保存 (一)
    Xcode4.5 本地化,多语言设置
    css3渐变画斜线 demo
    关于JavaScript的一些记录
    Windows 10 自带输入法(微软拼音)繁体简体切换快捷键
    ng-class用法小记
    基于vue监听滚动事件,实现锚点链接平滑滚动
    总结继承的几种方式
    浅谈jQuery的内部框架结构,操作
  • 原文地址:https://www.cnblogs.com/lin4xu/p/12896653.html
Copyright © 2011-2022 走看看