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. Node.js-安装配置【1】-在Windows XP系统配置环境变量

    家里有台老古董台式机,安装的是Windows XP系统,摸索了一下,成功的在上面安装配置好了Node.js V4.4.7 一.安装Node.js(过程略) 二.npm配置全局和缓存路径(过程略) 三. ...

  2. BlockCanary 一个轻量的,非侵入式的性能监控组件(阿里)

    开发者博客: BlockCanary — 轻松找出Android App界面卡顿元凶 开源代码:moduth/blockcanary BlockCanary对主线程操作进行了完全透明的监控,并能输出有 ...

  3. Apache虚拟主机配置,实现多域名访问本地项目PHP空间,以及配置403Forbidden等错误的解决办法

    第一步: apache主配置文件修改: 用文本编辑器打开apache的conf目录下 httpd.conf 将下面以下代码取消注释 LoadModule rewrite_module  modules ...

  4. 【BZOJ】3993: [SDOI2015]星际战争

    题意 \(m\)个人\(n\)个物品,第\(i\)个物品生命值为\(A_i\),第\(i\)个人每秒可以减少一个物品\(B_i\)的生命值,给出一个\(m \times n\)的矩阵,如果\(i\)行 ...

  5. POJ 1637 Sightseeing tour(混合图的欧拉回路)

    题目链接 建个图,套个模板. #include <cstdio> #include <cstring> #include <iostream> #include & ...

  6. Win 10 文件浏览器无法打开

    今天遇到个很奇怪的问题,文件浏览器File Explorer无法正常显示,点击打开后任务栏上已经显示打开了,但是屏幕上却看不到任何窗口,开始以为机子中了恶意的木马,然后就疯狂的查毒,然而并没有解决问题 ...

  7. Liunx下的有关于tomcat的相关操作 && Liunx 常用指令

    先记录以下liunx下的有关于tomcat的相关操作 查看tomcat进程: ps-ef|grep java (回车) 停止tomcat进程: kill -9 PID (进程号如77447) (回车) ...

  8. php 开启socket配置

    我在Windows命令行输入命令:C:\wamp\bin\php\php5.2.6\php.exe getXml.php以执行php文件. 出现错误:Fatal error: Call to unde ...

  9. Java 事件机制

    java事件机制包括三个部分:事件.事件监听器.事件源. 1.事件.一般继承自java.util.EventObject类,封装了事件源对象及跟事件相关的信息,用于listener的相应的方法之中,作 ...

  10. bug2--工程性错误

    1问题场景:图片上传失败,打印log.http header 有数据.不报错,通过流写入文件后,文件被创建,但是大小为0kb. 执行:df -h 发现linux的磁盘 used 100%. 原来是没有 ...