题目大意

POJ链接

有一个\(X×Y\)的房间,X代表墙壁,D是门,.代表人。这个房间着火了,人要跑出去,但是每一个时间点只有一个人可以从门出去。

问最后一个人逃出去的最短时间,如果不能逃出去,输出impossible

输入格式

第一行一个整数\(T\),表示有T组数据。

每组数据,第一行两个数字\(Y,X\),接下来有一个\(X×Y\)的图。

输出格式

\(T\)行答案,表示最后一个人逃出去的最短时间,如果不能逃出去,输出impossible

数据范围

\(3\le Y\le X\le 12\)

样例输入

3

5 5

XXDXX

X...X

D...X

X...D

XXXXX

5 12

XXXXXXXXXXXX

X..........D

X.XXXXXXXXXX

X..........X

XXXXXXXXXXXX

5 5

XDXXX

X.X.D

XX.XX

D.X.X

XXXDX

样例输出

3

21

impossible

思路

找到一个人之后,设他能到达某扇门的时间为\(t\),那么可以把从\(t\)到最大时间每一秒的这扇门和这个人建边,因为只要能到达,之后任何一秒都可以选择出去。从时间小的门的点开始匹配。看一下多长时间人和们都能匹配上。

查询人到门的距离用BFS,而最后求答案要用二分。

代码

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int maxn=1e6+10;
const int dx[4]={0,0,1,-1};
const int dy[4]={1,-1,0,0};
int x,y;
char g[20][20];
int match[maxn]; struct Edge{
int to,nxt,val;
}edge[maxn]; struct Node{
int x,y,t;
Node(){}
Node(int a,int b,int c){
x=a;y=b;t=c;
}
}; int head[maxn],tot;
void add(int a,int b,int w){
edge[++tot].to=b;
edge[tot].val=w;
edge[tot].nxt=head[a];
head[a]=tot;
} queue<Node> q;
int cal1(int a,int b){
return y*(a-1)+b;//两个数映射成一个数
} int cal2(int a,int b,int t){
return (cal1(a,b)-1)*100+t;
} void add2(int a,int b,int xx,int yy,int t){
for(int i=t;i<=100;i++)
add(cal1(a,b),cal2(xx,yy,i),i);//把这个人和之后分成的多个门建边
} bool vis[20][20];
void bfs(int a,int b){
memset(vis,0,sizeof(vis));
vis[a][b]=true;
q.push(Node(a,b,0));
while(!q.empty()){
Node now=q.front();q.pop(); for(int i=0;i<4;i++){
int xx=now.x+dx[i];
int yy=now.y+dy[i]; if(xx>=1&&xx<=x&&yy>=1&&yy<=y&&!vis[xx][yy]&&g[xx][yy]=='.'){
vis[xx][yy]=true;
q.push(Node(xx,yy,now.t+1));
} if(xx>=1&&xx<=x&&yy>=1&&yy<=y&&!vis[xx][yy]&g[xx][yy]=='D'){
vis[xx][yy]=true;
add2(a,b,xx,yy,now.t+1);//找到了门
}
}
}
} bool vis2[maxn];
bool dfs(int x,int t){
for(int i=head[x];i;i=edge[i].nxt){
if(vis2[edge[i].to]||edge[i].val>t)continue;
vis2[edge[i].to]=true;
if(match[edge[i].to]==0||dfs(match[edge[i].to],t)){
match[edge[i].to]=x;
return true;
}
}
return false;
} bool judge(int t){
memset(match,0,sizeof(match));
for(int i=1;i<=x;i++)
for(int j=1;j<=y;j++)
if(g[i][j]=='.'){
memset(vis2,0,sizeof(vis2));
if(!dfs(cal1(i,j),t))return false;
}
return true;
} void arrclear(){
memset(head,0,sizeof(head)); } int main(){
freopen("123.txt","r",stdin); int T;
scanf("%d",&T);
while(T--){
arrclear();
scanf("%d%d",&x,&y); tot=0;
for(int i=1;i<=x;i++)
for(int j=1;j<=y;j++)
scanf(" %c",&g[i][j]); for(int i=1;i<=x;i++)
for(int j=1;j<=y;j++)
if(g[i][j]=='.')bfs(i,j);//找到人bfs int l=0,r=100;//卡的贼严,还是开小点
while(l<=r){//二分答案
int mid=(l+r)/2;
if(judge(mid))r=mid-1;
else l=mid+1;
}
if(l==100+1)printf("impossible\n");
else printf("%d\n",l);
}
return 0;
}

【最大匹配+二分答案】POJ 3057 Evacuation的更多相关文章

  1. 【最大匹配+二分答案】HDU 2236 无题II

    题目内容 这是一个简单的游戏,在一个\(n×n\)的矩阵中,找\(n\)个数使得这\(n\)个数都在不同的行和列里并且要求这\(n\)个数中的最大值和最小值的差值最小. 输入格式 输入一个整数\(T\ ...

  2. POJ 3057 Evacuation 二分+最大流

    Evacuation 题目连接: http://poj.org/problem?id=3057 Description Fires can be disastrous, especially when ...

  3. POJ 3057 Evacuation (二分匹配)

    题意:给定一个图,然后有几个门,每个人要出去,但是每个门每个秒只能出去一个,然后问你最少时间才能全部出去. 析:初一看,应该是像搜索,但是怎么保证每个人出去的时候都不冲突呢,毕竟每个门每次只能出一个人 ...

  4. POJ 3057 Evacuation(二分匹配)

    分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d ...

  5. POJ 3057 Evacuation 题解

    题目 Fires can be disastrous, especially when a fire breaks out in a room that is completely filled wi ...

  6. POJ 3057 Evacuation(二分图匹配+BFS)

    [题目链接] http://poj.org/problem?id=3057 [题目大意] 给出一个迷宫,D表示门,.表示人,X表示不可通行, 每个门每时间单位只允许一个人通过, 每个人移动一格的为一时 ...

  7. POJ 3057 Evacuation 二分图匹配

    每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:10240000 ...

  8. TTTTTTTTTTTTT poj 3057 Evacuation 二分图匹配+bfs

    题意:见挑战230页 #include <iostream> #include <cstdio> #include <cstring> #include <c ...

  9. [poj] 3057 Evacuation

    原题 题目大意 墙壁"X",空区域(都是人)".", 门"D". 人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移 ...

随机推荐

  1. Promise核心实现

    核心 构造函数核心 维护状态变量,只能由pending变为resolve或者reject 维护一个存储结果的变量 维护一个回调数组,执行到then,如果我们传入的立即执行函数没有立即执行resolve ...

  2. why哥被阿里一道基础面试题给干懵了,一气之下写出万字长文。

    这是why的第 65 篇原创文章 荒腔走板 大家好,我是 why,欢迎来到我连续周更优质原创文章的第 65 篇.老规矩,先荒腔走板聊聊技术之外的东西. 上面这图是去年的成都马拉松赛道上,摄影师抓拍的我 ...

  3. 关于“枚举{0,1,...,n-1}所包含的所有大小为k的子集”的理解

    前言 今天整理以前的竞赛笔记时,发现了当时写的一个模板: 枚举{0,1,-,n-1}所包含的所有大小为k的子集: int comb = (1 << k) - 1; while (comb ...

  4. bernoulli, multinoulli distributions 讲解

    bernoulli, multinoulli distributions 讲解   常用概率分布-Bernoulli 分布 & Multinoulli 分布 转自:迭代自己-19常用概率分布 ...

  5. maoge数

    maoge数 题目描述 maoge定义一个数x是maoge数的条件,当且仅当x的各数位之和等于 x / 2向下取整,现在maoge想让你求 n 的约数中有多少个maoge数 输入格式 输入一个数 n ...

  6. netty全局分析1

    这个系列都是别人的分析文 https://www.jianshu.com/p/ac7fb5c2640f 一丶 Netty基础入门 Netty是一个高性能.异步事件驱动的NIO框架,它提供了对TCP.U ...

  7. Java Web学习(五)session、cookie、token

    文章更新时间:2020/09/14 一.引言 动态网页兴起后,会话管理变成开发者需要考虑的一个问题,由于HTTP请求是无状态的,为了区分每个用户,此时引入了会话标识(sessionId)的概念,但是存 ...

  8. Android开发中导入第三方库所遇问题记录

    1.重复循环依赖的问题 (1)需求 如下图所示: 在Android 项目中,采用模块化开发,一个是主跑application--Mudule A,另外一个是library--Library B 1)M ...

  9. 如何下载jmeter旧版本

    推荐先用旧版本做好测试基本操作,因为高版本不适合做压力测试,需要证书,有点麻烦. 1.百度或直接打开jmeter官网:https://jmeter.apache.org/ 2.向下拖到Archives ...

  10. macOS提示“将对您的电脑造成伤害……“进阶版

    > 很多小伙伴在更新完系统后运行应用会闪退以及提示"xxxx 将对您的电脑造成伤害. 您应该将它移到废纸篓",本文将针对此问题提供解决方法.如图:![-w456](https ...