【最大匹配+二分答案】POJ 3057 Evacuation
题目大意
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的更多相关文章
- 【最大匹配+二分答案】HDU 2236 无题II
题目内容 这是一个简单的游戏,在一个\(n×n\)的矩阵中,找\(n\)个数使得这\(n\)个数都在不同的行和列里并且要求这\(n\)个数中的最大值和最小值的差值最小. 输入格式 输入一个整数\(T\ ...
- POJ 3057 Evacuation 二分+最大流
Evacuation 题目连接: http://poj.org/problem?id=3057 Description Fires can be disastrous, especially when ...
- POJ 3057 Evacuation (二分匹配)
题意:给定一个图,然后有几个门,每个人要出去,但是每个门每个秒只能出去一个,然后问你最少时间才能全部出去. 析:初一看,应该是像搜索,但是怎么保证每个人出去的时候都不冲突呢,毕竟每个门每次只能出一个人 ...
- POJ 3057 Evacuation(二分匹配)
分析: 这是一个时间和门的二元组(t,d)和人p匹配的问题,当我们固定d0时,(t,d0)匹配的人数和t具有单调性. t增加看成是多增加了边就行了,所以bfs处理出p到每个d的最短时间,然后把(t,d ...
- POJ 3057 Evacuation 题解
题目 Fires can be disastrous, especially when a fire breaks out in a room that is completely filled wi ...
- POJ 3057 Evacuation(二分图匹配+BFS)
[题目链接] http://poj.org/problem?id=3057 [题目大意] 给出一个迷宫,D表示门,.表示人,X表示不可通行, 每个门每时间单位只允许一个人通过, 每个人移动一格的为一时 ...
- POJ 3057 Evacuation 二分图匹配
每个门每个时间只能出一个人,那就把每个门拆成多个,对应每个时间. 不断增加时间,然后增广,直到最大匹配. //#pragma comment(linker, "/STACK:10240000 ...
- TTTTTTTTTTTTT poj 3057 Evacuation 二分图匹配+bfs
题意:见挑战230页 #include <iostream> #include <cstdio> #include <cstring> #include <c ...
- [poj] 3057 Evacuation
原题 题目大意 墙壁"X",空区域(都是人)".", 门"D". 人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移 ...
随机推荐
- SpringBoot2 集成日志,复杂业务下的自定义实现
本文源码:GitHub·点这里 || GitEE·点这里 一.日志体系集成 1.日志管理 在系统的开发中,最关键的一个组件工具就是日志,日志打印方便问题排查,或者生产事故回溯,日志记录用来监控并分析系 ...
- Android组件化 + MVP + MVVM
前言 组件化和插件化已经提出了很久了,到现在也是比较稳定的一种架构方案了,在三年前,组件化和插件提出来没多久,前公司就已经在项目中使用了,只是当时还只是菜鸟,没有资格参与到架构的建设中,只是在大佬搭好 ...
- JZOJ1495 宝石
Description 见上帝动了恻隐之心,天后也想显示一下慈悲之怀,随即从口袋中取出一块魔术方巾,让身边的美神维纳斯拿到后堂的屏风上去试试,屏风是正方形的,高和宽方向上各划有m条鱼屏风的边平行的直线 ...
- DevOps-实践心得
基于最近几年从事与DevOps的相关实践,对这篇文章的观点深有体会,所以记录在这里.加粗部分是我比较深有体会的,但是对于最后作者对于"运维"有些悲观,我有点不敢苟同,反而对于运维的 ...
- App测试理论简介
一.App测试常见关注点 1.App的功能测试 功能测试都是我们首要测试的,只有功能实现了才算符合上线发布的最低标准.我们需要检测产品功能是否已实现.产品功能是否符合设计要求.产品功能是否有重复.产品 ...
- 《Java从入门到失业》第四章:类和对象(4.2):String类
4.2String类 这一节,我们学习第一个类:String类.String翻译成汉语就是“字符串”,是字符的序列.我们知道,在Java中,默认采用Unicode字符集,因此字符串就是Unicode字 ...
- 工具类-Fastjson入门使用
简介 什么是Fastjson? fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到Java ...
- 数据库分表分区后的ID生成之雪花生成
转自https://www.cnblogs.com/jajian/p/11101213.html 传统的单体架构的时候,我们基本是单库然后业务单表的结构.每个业务表的ID一般我们都是从1增,通过AUT ...
- 3.GoolgeProtoBuffer序列化反序列化
- Java List 常用集合 ArrayList、LinkedList、Vector
Java 中的 List 是非常常用的数据类型.List 是有序的 Collection,Java List 一共有三个实现类,分别是:ArrayList.Vector.LinkedList 本文分析 ...