题目分享L 二代目
Posted lin4xu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题目分享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; }
以上是关于题目分享L 二代目的主要内容,如果未能解决你的问题,请参考以下文章