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】Remove Nth Node From End of List(easy)
Given a linked list, remove the nth node from the end of list and return its head. For example, Give ...
- jsp通过s:hidden传值给后台,后台数据出现了若干逗号问题
<s:iterator value="rpActionVO.page.result" id="list" status="st"> ...
- 让view 覆盖导航栏
当我们想做一个弹出式菜单时,想将导航栏也一起盖住不显示的话,可以用如下语句实现: UIView* myView = /* 你自定义的view */; UIWindow* currentWindow = ...
- asp.net 曲线图
public void draw(DataTable dt) { //取得记录数量 int count = dt.Rows.Count; //记算图表宽度 int wd = 80 + 20 * (co ...
- 解决Windows10下80端口被PID为4的System占用的问题
一.背景 最近由于好奇心,更新了windows10系统,感觉上手还蛮快,而且体验还不错,但是在IDEA中做开发时,使用80端口进行启动项目的时候发现端口被占用了,于是尝试解决这个问题.具体步骤如下,分 ...
- [Android Pro] Android打包一个Apk后,如何查看它的VersionCode、VersionName 等等。
Android打包成Apk后,其实是一个压缩文件,我们用winrar打开也能看到里面的文件结构.还能看到AndroidManifest.但是里面的内容有点问题. 不知道是因为加密还是Android就是 ...
- Android接口传递Json数组的处理方式
public static XTResult<Void> addTravel(String uuid, String travelName, String travelId, String ...
- bnuoj 24251 Counting Pair
一道简单的规律题,画出二维表将数字分别相加可以发现很明显的对称性 题目链接:http://www.bnuoj.com/v3/problem_show.php?pid=24251 #include< ...
- ISD1700系列多段语音录放系列
ISD1700系列语音芯片的基础指示:
- js 倒计时点击和当前时间
<input id="btn" type="submit" value="确定" disabled="disabled&qu ...