3566 紧急疏散

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
 
 
题目描述 Description

发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

输入描述 Input Description

输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

输出描述 Output Description

只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出'impossible'(不包括引号).

样例输入 Sample Input

5 5  
XXXXX
X...D
XX.XX
X..XX
XXDXX

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

3<=N <=20,3<=M<=20

题解:

 对于每个门进行一次bfs,得出每个点到每个门的时间
 然后二分时间,每次建图dinic
 S到空地连一条容量1的边,
 每个空地到可到达的门连一条容量1的边,
 每个门到T连一条容量为时间的边

代码:

(对于codevs来说):

 #include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 0x7fffffff
#define maxn 1001
#define S 0
#define T 1000 using namespace std; int n,m,head[maxn],dis[][][],ans,tot,cnt=,door=,layered[maxn],map[][],finallyans=-;
int xx[]={,,,-},yy[]={,-,,}; struct ss
{
int x;
int y;
int s;
ss() {};
ss(int a,int b,int c)
{
x=a;
y=b;
s=c;
};
}; struct node
{
int to;
int next;
int edge;
}e[]; void add(int u,int v,int c)
{
e[++cnt].to=v;
e[cnt].next=head[u];
e[cnt].edge=c;
head[u]=cnt;
} void insert(int u,int v,int c)
{
add(u,v,c);
add(v,u,);
} bool bfs()
{
for (int i=;i<=T;i++) layered[i]=INF;
queue<int>que;
que.push(S);
while (!que.empty())
{
int now=que.front();
que.pop();
for (int i=head[now];i;i=e[i].next)
if (e[i].edge&&layered[e[i].to]>layered[now]+)
{
layered[e[i].to]=layered[now]+;
que.push(e[i].to);
if (e[i].to==T) return ;
}
}
return ;
} int dfs(int x,int inf)
{
if (x==T) return inf;
int rest=inf;
for (int i=head[x];i&&rest;i=e[i].next)
if (e[i].edge&&layered[e[i].to]==layered[x]+)
{
int now=dfs(e[i].to,min(rest,e[i].edge));
if (!layered[now]) layered[now]=;
e[i].edge-=now;
e[i^].edge+=now;
rest-=now;
}
return inf-rest;
} int dinic()
{
int ansn=;
while (bfs()) ansn+=dfs(S,INF);
return ansn;
} void built(int x)
{
memset(head,,sizeof (head));
cnt=;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (map[i][j]==)
{
int v=(i-)*m+j;
insert(S,v,);
}
for (int i=;i<=door;i++) insert(n*m+i,T,x);
for (int i=;i<=door;i++)
for (int j=;j<=n;j++)
for (int k=;k<=m;k++)
if (dis[i][j][k]<=x) insert((j-)*m+k,n*m+i,x);
} bool judge(int x)
{
built(x);
int ans=dinic();
if (ans==tot) return ;
else return ;
} void search(int k,int x,int y)
{
queue<ss>que;
que.push(ss(x,y,));
while (!que.empty())
{
for (int i=;i<;i++)
{
int nowx=que.front().x+xx[i];
int nowy=que.front().y+yy[i];
int s=que.front().s;
if(nowx<||nowy<||nowx>n||nowy>m||map[nowx][nowy]!=) continue;
if (dis[k][nowx][nowy]==INF)
{
dis[k][nowx][nowy]=s+;
que.push(ss(nowx,nowy,s+));
}
}
que.pop();
}
}
int main()
{
char ch[];
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++)
{
scanf("%s",ch);
for (int j=;j<=m;j++)
{
if (ch[j-]=='.') map[i][j]=,tot++;
if (ch[j-]=='D') map[i][j]=++door;
}
}
for (int i=;i<=door;i++)
for (int j=;j<=n;j++)
for (int k=;k<=m;k++)
dis[i][j][k]=INF;
for (int i=;i<=n;i++)
for (int j=;j<=m;j++)
if (map[i][j]>) search(map[i][j],i,j);
int l=,r=;
while (l<=r)
{
int mid=(l+r)>>;
if (judge(mid)) finallyans=r=mid,r--;
else l=mid+;
}
if (finallyans==-) printf("impossible");
else printf("%d",finallyans);
return ;
}

对于bzoj来说:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mid (l+r)/2
#define inf 0x7fffffff
#define T n*n*m*m+2
const int N=;
const int M=;
char s[N];
bool use[N][N],flag[N][N];
struct S{int x,y,c;}l[N*N];
struct Q{int st,en,va;}aa[M*];
int n,m,map[N][N],f[N][N][N][N],sum,point[M],next[M*],cur[M],dis[M],pre[M],gap[M],tot;
int xi[]={-,,,},yi[]={,-,,};
inline void bfs(int xa,int ya){
int i,h,t,k,x,y;
memset(use,,sizeof(use));
h=t=;l[h].x=xa;l[h].y=ya;l[h].c=;
while(h<=t){
x=l[h].x;y=l[h].y;
for(i=;i<;++i){
int xx=x+xi[i],yy=y+yi[i];
if(xx>&&xx<=n&&yy>&&y<=m&&map[xx][yy]==&&use[xx][yy]){
l[++t].x=xx;l[t].y=yy;l[t].c=l[h].c+;
use[xx][yy]=false;
f[xx][yy][xa][ya]=l[t].c;
flag[xx][yy]=true;
}
}
h+=;
}
}
inline void add(int x,int y,int z){
tot+=;next[tot]=point[x];point[x]=tot;
aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;
tot+=;next[tot]=point[y];point[y]=tot;
aa[tot].st=y;aa[tot].en=x;aa[tot].va=;
}
inline int ISAP(int ss,int tt){
bool f;
int minn,ans=,i,u,y;
memset(dis,,sizeof(dis));
memset(gap,,sizeof(gap));
memset(pre,,sizeof(pre));
gap[]=tt-ss+; u=ss;
for(i=ss;i<=tt;++i) cur[i]=point[i];
while(dis[ss]<tt-ss+){
f=false;
for(i=cur[u];i;i=next[i])
if(aa[i].va>&&dis[u]==dis[aa[i].en]+){
cur[u]=i;f=true;break;
}
if(f){
pre[u=aa[i].en]=i;
if(u==tt){
minn=inf;
for(i=u;i!=ss;i=aa[pre[i]].st)
minn=min(minn,aa[pre[i]].va);
ans+=minn;
for(i=u;i!=ss;i=aa[pre[i]].st){
aa[pre[i]].va-=minn;
aa[pre[i]^].va+=minn;
}
u=ss;
}
}
else{
--gap[dis[u]];
if(!gap[dis[u]]) return ans;
y=*tt; cur[u]=point[u];
for(i=point[u];i;i=next[i])
if(aa[i].va>) y=min(y,dis[aa[i].st]);
++gap[dis[u]=y+];
if(u!=ss) u=aa[pre[u]].st;
}
}
return ans;
}
inline bool check(int x){
int i,j,p,q;
tot=;
memset(point,,sizeof(point));
memset(next,,sizeof(next));
for(i=;i<=n;++i)
for(j=;j<=m;++j){
int now=((i-)*m+j-)*n*m;
if(map[i][j]==){
for(p=;p<x;++p)
add(now+p+,now+p+,inf),add(now+p+,T,);
add(now+x+,T,);
}
if(map[i][j]==){
add(,now+,);
for(p=;p<=n;++p)
for(q=;q<=m;++q)
if(f[i][j][p][q])
add(now+,((p-)*m+q-)*n*m+f[i][j][p][q]+,);
}
}
return ISAP(,T)==sum;
}
int main(){
int i,j;
scanf("%d%d",&n,&m);
for(i=;i<=n;++i){
scanf("%s",&s);
for(j=;j<m;++j){
if(s[j]=='D') map[i][j+]=;
if(s[j]=='.') map[i][j+]=,sum+=;
if(s[j]=='X') map[i][j+]=;
}
}
for(i=;i<=n;++i)
for(j=;j<=m;++j)
if(map[i][j]==)
bfs(i,j);
for(i=;i<=n;++i)
for(j=;j<=m;++j)
if(!flag[i][j]&&map[i][j]==){
printf("impossible\n");
return ;
}
int l=,r=n*m,ans=inf;
while(l<r){
if(check(mid)) ans=min(ans,mid),r=mid;
else l=mid+;
}
printf("%d\n",ans);
}

C++之路进阶——codevs3566(紧急疏散)的更多相关文章

  1. C++之路进阶codevs1269(匈牙利游戏)

    1269 匈牙利游戏 2012年CCC加拿大高中生信息学奥赛  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond       题目描述 Description ...

  2. C++之路进阶——优先队列优化最短路径算法(dijkstra)

    一般的dijkstra算法利用贪心的思想,每次找出最短边,然后优化到其他点的的距离,我们还采用贪心思路,但在寻找最短边进行优化,之前是双重for循环,现在我们用优先队列来实现. 代码解释: //样例程 ...

  3. C++之路进阶——HDU1880(魔咒词典)

    ---恢复内容开始--- New~ 欢迎参加2016多校联合训练的同学们~ 魔咒词典 Time Limit: 8000/5000 MS (Java/Others)    Memory Limit: 3 ...

  4. C++之路进阶——poj3461(Oulipo)

    Oulipo Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35694   Accepted: 14424 Descript ...

  5. C++之路进阶——P2022

    P2022 有趣的数 让我们来考虑1到N的正整数集合.让我们把集合中的元素按照字典序排列,例如当N=11时,其顺序应该为:1,10,11,2,3,4,5,6,7,8,9. 定义K在N个数中的位置为Q( ...

  6. C++之路进阶codevs1242(布局)

    1242 布局 2005年USACO  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold    <:section class="hbox" ...

  7. C++之路进阶——codevs3333(高级打字机)

    3333 高级打字机  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master     题目描述 Description 早苗入手了最新的高级打字机.最新款自然有着与 ...

  8. C++之路进阶——codevs1789(最大获利)

    1789 最大获利 2006年NOI全国竞赛  时间限制: 2 s  空间限制: 128000 KB  题目等级 : 大师 Master       题目描述 Description 新的技术正冲击着 ...

  9. C++之路进阶——codevs2306(晨跑)

    2306 晨跑 2009年省队选拔赛山东  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master       题目描述 Description Elaxia最近迷恋 ...

随机推荐

  1. ZeroMQ接口函数之 :zmq - 0MQ 轻量级消息传输内核

    官方网址:http://api.zeromq.org/4-0:zmq zmq(7) 0MQ Manual - 0MQ/3.2.5 Name zmq – ØMQ 轻量级消息传输内核 Synopsis # ...

  2. VerifyCodeUtil.java

    package com.vcredit.framework.utils; import java.awt.Color;import java.awt.Font;import java.awt.Grap ...

  3. JS全兼容检测浏览器类型及版本

    直接上代码: <script> var browser = (function () { var isIE6 = /msie 6/i.test(navigator.userAgent); ...

  4. 重置dns

    flusdns

  5. spring mvc异常统一处理(ControllerAdvice注解)

    首先我的项目是一个为移动端提供的json数据的,当后台报错时如果为移动端返回一个错误页面显得非常不友好,于是通过ControllerAdvice注解返回json数据. 首先创建一个异常处理类: pac ...

  6. HTML5 头部标签定义

    <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 --> <html lang="zh-cmn-Hans"&g ...

  7. NC57,NC63-NC二开经验总结

    版主2010级市场营销专业本科生 2013年8月入达内培训Java相关技术 12月入职,做用友NC的二次开发工作 2015年4月离职,4中下旬入职一家互联网金融企业 下面是做NC二开期间积累的一些常用 ...

  8. VECTOR COMPUTATION

    COMPUTER OR GANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION Although the perform ...

  9. Symmetric Multiprocessor Organization

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION

  10. 2在HTML中使用JavaScript

    像HTML页面中插入JavaScrip的主要方法,就是使用<script>元素.HTML4.01为<script>定义了6个属性:async:可选,表示应该立即下载脚本,当不妨 ...