[HNOI2007]紧急疏散evacuate
时间限制: 1 Sec 内存限制: 128 MB提交: 60 解决: 10
题目描述
发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是".",那么表示这是一块空地;如果是"X",那么表示这是一面墙,如果是"D",那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。
输入
输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符"."、"X"和"D",且字符间无空格。
输出
只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出"impossible"(不包括引号)。
样例输入
5 5
XXXXX
X...D
XX.XX
X..XX
XXDXX
样例输出
3
提示
solution
这道题就是典型的网络流拆点,因为在每一时刻每一个门都能都能出去一个人,假设一个人到一个门的距离为x,那么他可以在x这个时间点以后,从这个门出去,就把门拆成不同的时间点,然后就可以二分总时间,然后把这个人与这个门从x到枚举的时间连一个流量为1的边,把所有的人与所有的门都这么处理,再把每一时刻的门与汇点连一条流量为1的边,在源点与每个人连一条流量为一的边,这样就能保证每个人只出去一次,每一时刻的门只出去一个人,之后在二分判断的时候,若最大流小于总人数返回非,大于等于总人数就返回真;
在间的时候可以吧不同时刻的门看成一个矩阵,这样既可以根据行列性质直接算出他们的标号,然后根据之前有的标号,同意加上一个值避免重复即可
1 #include<cmath> 2 #include<queue> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define INF 1000000 9 using namespace std; 10 11 int zhao; 12 int n,m,peo; 13 int a[30][30]; 14 int dor[30]; 15 int id[30][30]; 16 int dis[410][410]; 17 int mov[6][3]; 18 int jia; 19 int S,T; 20 21 struct node{ 22 int u,v,w,nxt; 23 }g[5000100]; 24 int adj[5000100],e; 25 void add(int u,int v,int w){ 26 g[e].v=v; g[e].u=u; g[e].w=w; 27 g[e].nxt=adj[u]; adj[u]=e++; 28 } 29 bool Jud(int x,int y,int i,int pos){ 30 int x1=x+mov[i][0] ,y1=y+mov[i][1]; 31 if(!(x1>=1 && x1<=n && y1>=1 && y1<=m)) return 0; 32 if(a[x1][y1]==0 || a[x1][y1]==2) return 0; 33 int pos2=(x+mov[i][0]-1)*m+ ( y+mov[i][1] ); 34 if(dis[pos2][pos]<10000) return 0; 35 return 1; 36 } 37 void find_short(int pos){ 38 queue<int> q; 39 q.push(pos); 40 dis[pos][pos]=0; 41 int k; 42 int x,y; 43 while(!q.empty()){ 44 k=q.front(); q.pop(); 45 //cout<<"k== "<<k<<endl; 46 x=(k-1)/m+1; y=k%m; if(y==0) y=m; 47 for(int i=1;i<=4;i++){ 48 if(Jud(x,y,i,pos)){ 49 int pos2=(x+mov[i][0]-1)*m+ ( y+mov[i][1] ); 50 dis[pos2][pos]=dis[k][pos]+1; 51 //cout<<"pos== "<<pos2<<" "<<pos<<" "<<dis[pos2][pos]<<endl; 52 q.push(pos2); 53 } 54 } 55 } 56 } 57 void init(){ 58 scanf("%d%d",&n,&m); 59 jia=n*n; 60 char s[30]; 61 for(int i=1;i<=n;i++){ 62 scanf("%s",&s); 63 for(int j=0;j<m;j++){ 64 if(s[j]=='.') a[i][j+1]=1,peo++; 65 else if(s[j]=='X') a[i][j+1]=0; 66 else if(s[j]=='D') a[i][j+1]=2; 67 } 68 } 69 for(int i=1;i<=n;i++) 70 for(int j=1;j<=m;j++){ 71 id[i][j]=m*(i-1)+j; 72 if(a[i][j]==2) dor[++dor[0]]=id[i][j]; 73 } 74 mov[1][0]=0; mov[1][1]=1; 75 76 mov[2][0]=0; mov[2][1]=-1; 77 mov[3][0]=1; mov[3][1]=0; 78 mov[4][0]=-1;mov[4][1]=0; 79 memset(dis,30,sizeof(dis)); 80 int x,y; 81 for(int i=1;i<=dor[0];i++){ 82 find_short(dor[i]); 83 } 84 } 85 bool nengpao(){ 86 for(int i=1;i<=n;i++){ 87 for(int j=1;j<=m;j++){ 88 bool ok=0; 89 if(a[i][j]==0 || a[i][j]==2) continue; 90 for(int k=1;k<=dor[0];k++){ 91 if(dis[id[i][j]][dor[k]]<10000) ok=1; 92 } 93 if(!ok) return 0; 94 } 95 } 96 return 1; 97 } 98 int dep[300010]; 99 bool BFS(){ 100 //if(zhao==149) cout<<zhao<<endl; 101 memset(dep,0,sizeof(dep)); 102 queue<int> q; int k; 103 dep[S]=1; 104 q.push(S); 105 while(!q.empty()){ 106 k=q.front(); q.pop(); 107 for(int i=adj[k];i!=-1;i=g[i].nxt){ 108 int v=g[i].v; 109 if(g[i].w && !dep[v]){ 110 dep[v]=dep[k]+1; 111 if(v==T) return 1; 112 q.push(v); 113 } 114 } 115 } 116 return 0; 117 } 118 int dfs(int x,int fw){ 119 //printf("x==%d fw==%d ",x,fw); 120 if(x==T) return fw; 121 int tmp=fw,k; 122 for(int i=adj[x];i!=-1;i=g[i].nxt){ 123 int v=g[i].v; 124 if(g[i].w && tmp && dep[v]==dep[x]+1){ 125 k=dfs(v,min(tmp,g[i].w)); 126 if(!k){ 127 dep[v]=0; 128 continue; 129 } 130 g[i].w-=k; g[i^1].w+=k; tmp-=k; 131 } 132 } 133 return fw-tmp; 134 } 135 bool check(int lim){ 136 int ch=lim; zhao=lim; 137 memset(adj,-1,sizeof(adj)); e=0; 138 for(int i=1;i<=dor[0];i++){ 139 for(int j=1;j<=lim;j++){ 140 add((i-1)*ch+j+jia,T,1); add(T,(i-1)*ch+j+jia,0); 141 } 142 } 143 for(int i=1;i<=n;i++){ 144 for(int j=1;j<=m;j++){ 145 //cout<<"id2=="<<id[i][j]<<endl; 146 if(a[i][j]==0 || a[i][j]==2) continue; 147 //cout<<"id== "<<id[i][j]<<endl; 148 add(S,id[i][j],1); add(id[i][j],S,0); 149 for(int k=1;k<=dor[0];k++){ 150 if(dis[id[i][j]][dor[k]]>10000) continue; 151 for(int hh=dis[id[i][j]][dor[k]];hh<=lim;hh++){ 152 add(id[i][j],(k-1)*ch+hh+jia,1), add((k-1)*ch+hh+jia,id[i][j],0); 153 //if(lim==300) cout<<id[i][j]<<" "<<(k-1)*ch+hh+jia<<endl; 154 } 155 } 156 } 157 } 158 int he=0,tan; 159 while(BFS()){ 160 while(tan=dfs(S,INF)){ he+=tan; } 161 } 162 //cout<<"lim== "<<lim<<" "<<he<<endl; 163 if(he>=peo) return 1; 164 else return 0; 165 166 } 167 void work(){ 168 S=0; T=300000; 169 int l=0,r=600,mid,ans=600; 170 while(l<=r){ 171 mid=(l+r)>>1; 172 if(check(mid)) ans=mid,r=mid-1; 173 else l=mid+1; 174 } 175 printf("%d ",ans); 176 return; 177 } 178 int main(){ 179 //freopen("a.in","r",stdin); 180 //freopen("a.out","w",stdout); 181 init(); 182 bool ok=nengpao(); 183 if(!ok){ 184 printf("impossible "); 185 return 0; 186 } 187 work(); 188 return 0; 189 190 }