【最大匹配+二分答案】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". 人向门移动通过时视为逃脱,门每秒能出去一个人,人可以上下左右移动,墙阻止移 ...
随机推荐
- bernoulli, multinoulli distributions 讲解
bernoulli, multinoulli distributions 讲解 常用概率分布-Bernoulli 分布 & Multinoulli 分布 转自:迭代自己-19常用概率分布 ...
- 【转】PHP面试总结
文章出处:https://www.cnblogs.com/codetao/p/6418127.html
- SSM框架整合核心内容
所需要的jar包及其版本 Spring 版本:4.3.18 tx.aop.beans.core.web.web-mvc.context.expression.jdbc MyBatis:3.4.6 ...
- CSS 常见样式 特殊用法 贯穿线&徽章&箭头
### 贯穿渐变线,中间插值- 如图: >  ![在这里插入图片描述 ...
- netty字符串流分包
@Override protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Obj ...
- JDK8在windows系统下安装
一.下载 下载地址:https://www.oracle.com/technetwork/java/javase/downloads/index.html#JDK8 目前大部分公司内部使用的还是jdk ...
- leetcode560题解【前缀和+哈希】
leetcode560.和为K的子数组 题目链接 算法 前缀和+哈希 时间复杂度O(n). 在解决这道题前需要先清楚,一个和为k的子数组即为一对前缀和的差值. 1.我们假设有这么一个子数组[i,j]满 ...
- Jmeter(二十三) - 从入门到精通 - JMeter函数 - 上篇(详解教程)
1.简介 在性能测试中为了真实模拟用户请求,往往我们需要让提交的表单内容每次都发生变化,这个过程叫做参数化.JMeter配置元件与前置处理器都能帮助我们进行参数化,但是都有局限性,为了帮助我们能够更好 ...
- linux学习(十一)linux安装nginx
一.前言 由于本地练手的小demo用的是vue+spring boot来玩的,所以部署的时候想着用Nginx来实现反向代理[即请求转发,解决前后端分离的跨域请求问题],既然要用,那么首先得在服务器上面 ...
- 深入理解HBase
深入理解HBase: https://www.jianshu.com/p/b23800d9b227