题目大意

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. python的logging模块及应用

    一.logging日志模块等级 常见log级别从高到低: CRITICAL >ERROR >WARNING >INFO >DEBUG,默认等级为WARNING,即>=WA ...

  2. JS -- JavaScript简介

    JavaScript是一种属于网络的高级脚本语言(解释性脚本语言),已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果. 一.如何插入JS代码? 使用&l ...

  3. [06] 优化C#服务器的思路和工具的使用

    优化C#服务器的思路和工具的使用 优化服务器之前, 需要先对问题的规模做合理的预估, 然后对关键的数据做采样, 做对比, 看和自己的预估是否一致, 误差大在什么地方, 是预估的不对, 还是系统实现有问 ...

  4. command三国杀开发日记20200914

    目前状态 一时脑热开始写的东西,计划完全使用C语言实现,尽量使用通用接口,能够在windows上直接运行 几乎是一穷二白,初步搭建了牌堆.玩家信息接口体,编写了简单的UI函数,能够将玩家信息显示在屏幕 ...

  5. 分别用canvas和css3的transform做出钟表的效果

    两种方式实际上在js上的原理都是一样的.都是获取时间对象,再获取时间对象的时分秒,时分秒乘以其旋转一刻度(一秒.一分.一小时)对应的角度.css3中要赋值于transform:rotate(角度),c ...

  6. 14个Spring MVC顶级技巧,随时用随时爽,一直用一直爽~

    通常,在Spring MVC中,我们编写一个控制器类来处理来自客户端的请求.然后,控制器调用业务类来处理与业务相关的任务,然后将客户端重定向到逻辑视图名称,该名称由Spring的调度程序Servlet ...

  7. golang 协程学习

    协程数据传递问题 func TestGoroutineData(t *testing.T) { var wg sync.WaitGroup wg.Add(1) i := 0 go func(j int ...

  8. Spring学习(八)AOP详解

    文章更新时间:2020/04/06 一.一个例子 在上面的例子中,包租婆的核心业务就是签合同,收房租,那么这就够了,灰色框起来的部分都是重复且边缘的事,交给中介商就好了,这就是 AOP 的一个思想:让 ...

  9. django中url和reverse使用

    使用url标签和reverse()函数,可以避免在模板和view中对url进行硬编码,这样即使url改变了,对模板和view也没有影响, 其实在模板, view中,如果想获取当前访问的url,那用re ...

  10. 编程体系结构(04):JavaIO流文件管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.IO流分类 1.分类角度 流的方向 输入流:从数据源中读取数据到应用中的流: 输出流:从应用中将数据写入到目的地的流: 流数据类型 字节流 ...