BZOJ 1189 [HNOI2007]紧急疏散evacuate
Description
发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。
Input
输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。
Output
只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出'impossible'(不包括引号)。
Sample Input
XXXXX
X...D
XX.XX
X..XX
XXDXX
Sample Output
HINT
2015.1.12新加数据一组,鸣谢1756500824
C++语言请用scanf("%s",s)读入!
【题目分析】
枚举每一个答案t,对于每一个格子,拆成t+1个点,分别代表每一时刻的这个点,然后建边,每次增大t的时候,再加入一层点,然后满流之后就可以得到答案了。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <set>
//#include <map>
#include <string>
#include <algorithm>
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
#define maxn 1000005
#define inf (0x3f3f3f3f)
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
int n,m,S,T;
char s[21];
int a[21][21]; // 0 X 1 . 2 D
int hs[21][21][201];
int mov[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
int fr[maxn],h[maxn],to[maxn],fl[maxn],en=0,ne[maxn];
void add(int a,int b,int r)
{
to[en]=b; fr[en]=a; fl[en]=r; ne[en]=h[a]; h[a]=en++;
to[en]=a; fr[en]=b; fl[en]=0; ne[en]=h[b]; h[b]=en++;
}
int map[maxn];
bool tell()
{
memset(map,-1,sizeof map);
queue <int> q;
while (!q.empty()) q.pop();
q.push(S); map[S]=0;
while (!q.empty())
{
int x=q.front(); q.pop();
for (int i=h[x];i>=0;i=ne[i])
{
if (fl[i]>0&&map[to[i]]==-1)
{
map[to[i]]=map[x]+1;
q.push(to[i]);
}
}
}
if (map[T]==-1) return false;
return true;
}
int zeng(int k,int now)
{
if (k==T) return now;
int ret=0;
for (int i=h[k];i>=0&&now>ret;i=ne[i])
{
if (fl[i]>0&&map[to[i]]==map[k]+1)
{
int tmp=zeng(to[i],min(fl[i],now-ret));
ret+=tmp; fl[i]-=tmp; fl[i^1]+=tmp;
}
}
if (!ret) map[k]=-1;
return ret;
}
void init()
{memset(h,-1,sizeof h);en=0;}
int dinic()
{
int r=0,t;
while (tell()) while (t=zeng(S,inf)) r+=t;
return r;
}
int sum=0,out=0;
int main()
{
n=read(); m=read();
for (int i=1;i<=n;++i)
{
scanf("%s",s+1);
for (int j=1;j<=m;++j)
{
if (s[j]=='X') a[i][j]=0;
else if (s[j]=='.') a[i][j]=1,sum++;
else if (s[j]=='D') a[i][j]=2;
}
}
init();S=0; T=maxn-1;
int cnt=0;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
for (int k=0;k<=200;++k)
hs[i][j][k]=++cnt;
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
if (a[i][j]==1)
add(S,hs[i][j][0],1);
for (int t=0;t<130;++t)
{
for (int i=1;i<=n;++i)
for (int j=1;j<=m;++j)
{
if (a[i][j]==1)
{
add(hs[i][j][t],hs[i][j][t+1],inf);
for (int l=0;l<4;++l)
{
int tx=i+mov[l][0],ty=j+mov[l][1];
if (tx<1||tx>n||ty<1||ty>m||a[tx][ty]==0) continue;
add(hs[i][j][t],hs[tx][ty][t+1],inf);
}
}
else if (a[i][j]==2)
{
add(hs[i][j][t],T,1);
add(hs[i][j][t],hs[i][j][t+1],inf);
}
}
out+=dinic();
if (out==sum)
{
printf("%d\n",t);
return 0;
}
}
printf("impossible\n");
}
BZOJ 1189 [HNOI2007]紧急疏散evacuate的更多相关文章
- BZOJ 1189: [HNOI2007]紧急疏散evacuate( BFS + 二分答案 + 匈牙利 )
我们可以BFS出每个出口到每个人的最短距离, 然后二分答案, 假设当前答案为m, 把一个出口拆成m个表示m个时间, 点u到出口v的距离为d, 那么u->v的[d, m]所有点连边, 然后跑匈牙利 ...
- bzoj 1189 [HNOI2007]紧急疏散evacuate 二分+网络流
[HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3626 Solved: 1059[Submit][St ...
- bzoj 1189: [HNOI2007]紧急疏散evacuate 分层图最大流_拆点_二分
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是 ...
- 【BZOJ】1189: [HNOI2007]紧急疏散evacuate(二分+bfs+网络流)
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 表示完全不会QAQ.... 于是膜拜题解orz 二分时间........... 于是转换成判定 ...
- 1189: [HNOI2007]紧急疏散evacuate - BZOJ
Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一 ...
- 1189: [HNOI2007]紧急疏散evacuate
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3831 Solved: 1119[Submit][Status][Discuss] Descript ...
- bzoj千题计划132:bzoj1189: [HNOI2007]紧急疏散evacuate
http://www.lydsy.com/JudgeOnline/problem.php?id=1189 二分答案 源点向人连边,流量为1 门拆为mid个点,同一个门的第j个点向第j+1个点连边,流量 ...
- Bzoj1189 [HNOI2007]紧急疏散evacuate
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2293 Solved: 715 Descr ...
- BZOJ1189: [HNOI2007]紧急疏散evacuate 二分+最大流
1189: [HNOI2007]紧急疏散evacuate Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1132 Solved: 412[Submi ...
随机推荐
- 【leetcode】Course Schedule(middle)☆
There are a total of n courses you have to take, labeled from 0 to n - 1. Some courses may have prer ...
- MyEclipse/Eclipse中修改包的显示结构
操作如下:
- IOS- 堆和栈 详解
Objective-C的对象在内存中是以堆的方式分配空间的,并且堆内存是由你释放的,即release 栈由编译器管理自动释放的,在方法中(函数体)定义的变量通常是在栈内,因此如果你的变量要跨函数的话就 ...
- Target runtime Apache Tomcat v6.0 is not defined.错误解决方法
一.背景 最近在使用本地的tomcat进行运行项目的时候,发现出现了如题所述的问题.不知道什么原因,经过努力解决了该问题. 二.解决步骤 右击项目---选择属性---选择targeted runtim ...
- Caffe初试(一)win7_64bit+VS2013+Opencv2.4.10+CUDA6.5配置Caffe环境
折腾了几天,终于在windows系统上成功配置了Caffe环境,期间遇到了很多问题,每个问题的解决也都花了不少时间,查过挺多资料,感觉挺有意义,这里写篇博客记录一下. 原来我使用的CUDA版本是7.5 ...
- notifyDataSetInvalidated和notifyDataSetChanged有什么区别
notifyDataSetChanged方法通过一个外部的方法控制如果适配器的内容改变时需要强制调用getView来刷新每个Item的内容.public void notifyDataSetChang ...
- CLR via C#(12)-委托Delegate
本来按照进度应该学习事件了,可总觉得应该委托在前,事件在后,才好理解. 委托是一个类,它提供了回调函数机制,而且是类型安全的.使用委托可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数 ...
- jquery学习笔记-----插件开发的编写总结
一.对jQuery对象的扩展 ;(function($){ $.fn.extend( { fun1:abc,fun2:1bc … } ) })(jQuery) 这里采用立即执行模式,即不用调用也能执 ...
- Python 小游戏 Bunny
最近在学习Python,所以上网找了一个小程序练练手. 关于这款名为[Bunny]的小游戏,详细请看下面的链接: http://www.oschina.net/translate/beginning- ...
- sdut1598 周游列国【简单模拟题】
周游列国 Time Limit: 1000ms Memory limit: 32768K 有疑问?点这里^_^ 题目描述 题目链接:http://acm.sdut.edu.cn/sdutoj/p ...