BZOJ 1189[HNOI2007]紧急疏散evacuate

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

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

Sample Output

3

HINT

 

2015.1.12新加数据一组,鸣谢1756500824


C++语言请用scanf("%s",s)读入!

 
BFS处理出人到门的距离
二分答案,判断是否可以建边,S指向每一块空地,空地到门如果可以建边就建一条容量为x的边
每个门按照时间拆点,保证单位时间内走一次,然后跑最大流
代码太丑。。。
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 using namespace std;
  6 const int inf=100000000,N=161000;
  7 struct ee{int to,next,f;}e[5000001];
  8 struct bb{int x,y;}b[1010];
  9 int head[N],q[N*2],dis[N],dis1[410][21][21],map[21][21];
 10 int S,T,n,m,cnt=1,ans1,w,ans,door=1,num;
 11 char s[30];
 12 int fx[4]={0,0,1,-1},fy[4]={1,-1,0,0}; 
 13 void ins(int u,int v,int f){
 14     e[++cnt].to=v;e[cnt].f=f;e[cnt].next=head[u];head[u]=cnt;
 15     e[++cnt].to=u;e[cnt].f=0;e[cnt].next=head[v];head[v]=cnt;
 16 }
 17   
 18 bool bfs(){
 19     for (int i=1;i<=T;i++) dis[i]=inf;
 20     int h=0,t=1,now;
 21     q[1]=S;dis[S]=0;
 22     while(h!=t){
 23         now=q[++h];
 24         for (int i=head[now];i;i=e[i].next){
 25             int v=e[i].to;
 26             if (e[i].f&&dis[now]+1<dis[v]){
 27                 dis[v]=dis[now]+1;
 28                 if (v==T)return 1;
 29                 q[++t]=v;
 30             }
 31         }
 32     }
 33     if (dis[T]==inf) return 0; return 1;
 34 }
 35   
 36 int dinic(int now,int f){
 37     if (now==T) return f;
 38     int rest=f;
 39     for (int i=head[now];i;i=e[i].next){
 40         int v=e[i].to;
 41         if (e[i].f&&dis[v]==dis[now]+1&&rest){
 42             int t=dinic(v,min(rest,e[i].f));
 43             if (!t) dis[v]=0;
 44             e[i].f-=t;
 45             e[i^1].f+=t;
 46             rest-=t;
 47             //if(t) printf("%d %d %d\n",now,v,e[i].f);
 48         }
 49     }
 50     return f-rest;
 51 }
 52 void bfs1(int k,int x1,int y1){
 53     int h,t;h=t=0;
 54     b[++t].x=x1,b[t].y=y1;dis1[k][x1][y1]=0;
 55     while(h<t){
 56         int x=b[++h].x,y=b[h].y;
 57         for(int i=0;i<4;i++){
 58             int nx=x+fx[i],ny=y+fy[i];
 59             if(map[nx][ny]==1&&dis1[k][nx][ny]>dis1[k][x][y]+1){
 60                 dis1[k][nx][ny]=dis1[k][x][y]+1;
 61                 b[++t].x=x+fx[i],b[t].y=y+fy[i];
 62             }
 63         }
 64     }
 65 }
 66   
 67 void build(int x){
 68     memset(head,0,sizeof(head));
 69     memset(e,0,sizeof(e));
 70     for(int i=1;i<=n;i++)
 71         for(int j=1;j<=m;j++){
 72             if (map[i][j]==1) {
 73                 int u=(i-1)*m+j;
 74                 ins(S,u,1);
 75                 for(int k=2;k<=door;k++)
 76                     if(dis1[k][i][j]<=x) ins(u,dis1[k][i][j]+(k-2)*x+m*n,x);
 77             }
 78             if(map[i][j]>1){
 79                 for(int k=1;k<=x;k++){
 80                     int u=((map[i][j]-2)*x+k)+m*n;
 81                     if(k!=x)ins(u,u+1,x-k+1);
 82                     ins(u,T,1);
 83                 }
 84             }
 85         }
 86 } 
 87   
 88 bool judge(int x){
 89     build(x);
 90     ans=0;
 91     while(bfs()) 
 92     ans+=dinic(S,inf);
 93     if(ans>=num) return 1;
 94     return 0;
 95          
 96 }  
 97 int main(){
 98     scanf("%d%d",&n,&m);
 99     S=0,T=160010;
100     for(int i=1;i<=n;i++){
101             scanf("%s",s+1);
102             for(int j=1;j<=m;j++) {
103                 if (s[j]==.)map[i][j]=1,num++;
104                 else if(s[j]==D) map[i][j]=++door;
105             }
106         }
107     for(int i=2;i<=door;i++)
108         for(int j=1;j<=n;j++)
109             for(int k=1;k<=m;k++) dis1[i][j][k]=inf; 
110         for(int j=1;j<=n;j++)
111             for(int k=1;k<=m;k++) 
112                 if(map[j][k]>1) bfs1(map[j][k],j,k);
113     int l=0,r=400;
114     ans1=-1;
115     while(l<=r){
116         int mid=(l+r)>>1;
117         if(judge(mid)) ans1=mid,r=mid-1;
118         else l=mid+1;
119     }
120     if(ans1==-1) printf("impossible");
121     else printf("%d",ans1);
122 } 

 

以上是关于BZOJ 1189[HNOI2007]紧急疏散evacuate的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1189[HNOI2007]紧急疏散evacuate

[bzoj1189] [HNOI2007]紧急疏散evacuate

BZOJ1189[HNOI2007]紧急疏散evacuate 动态加边网络流

BZOJ 1189 [HNOI2007]紧急疏散evacuate

AC日记——[HNOI2007]紧急疏散evacuate bzoj 1189

BZOJ 1189 HNOI2007 紧急疏散evacuate