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
先bfs出最短路,再枚举时间t,用网络流来判断是否可以安全撤离(至于怎么证明它的正确性,我不知道,网上到处都是这样写的)
本来一直纠结在dis这个距离标号,我想继续利用上次的标号,后来发现不行因为断层以后,有的点距离标号变成最大的,就不能再经过它了,当时调了好久的说
1 const 2 fx:array[1..4]of longint=(1,0,-1,0); 3 fy:array[1..4]of longint=(0,1,0,-1); 4 var 5 map:array[0..20,0..20]of char; 6 node:array[0..20,0..20]of longint; 7 f:array[0..20,0..20,0..400]of longint; 8 door:array[0..400,0..1]of longint; 9 n,m,menn,doorn,tot:longint; 10 11 procedure init; 12 var 13 i,j:longint; 14 begin 15 readln(n,m); 16 for i:=1 to n do 17 begin 18 for j:=1 to m do 19 begin 20 read(map[i,j]); 21 if map[i,j]='.' then 22 begin 23 inc(menn); 24 inc(tot); 25 node[i,j]:=tot; 26 end; 27 if map[i,j]='D' then 28 begin 29 inc(doorn); 30 door[doorn,0]:=i; 31 door[doorn,1]:=j; 32 inc(tot); 33 node[i,j]:=tot; 34 end; 35 end; 36 readln; 37 end; 38 end; 39 40 var 41 flag,vis:array[0..20,0..20]of boolean; 42 x,y:array[0..410]of longint; 43 44 procedure bfs; 45 var 46 i,j,head,tail:longint; 47 begin 48 fillchar(f,sizeof(f),1<<7); 49 fillchar(vis,sizeof(vis),true); 50 for i:=1 to doorn do 51 begin 52 fillchar(flag,sizeof(flag),true); 53 f[door[i,0],door[i,1],i]:=0; 54 head:=1; 55 tail:=1; 56 x[1]:=door[i,0]; 57 y[1]:=door[i,1]; 58 flag[x[1],y[1]]:=false; 59 while head<=tail do 60 begin 61 for j:=1 to 4 do 62 if (x[head]+fx[j]>0)and(x[head]+fx[j]<=n)and(y[head]+fy[j]>0)and(y[head]+fy[j]<=m) then 63 if map[x[head]+fx[j],y[head]+fy[j]]='.' then 64 if flag[x[head]+fx[j],y[head]+fy[j]] then 65 begin 66 inc(tail); 67 x[tail]:=x[head]+fx[j]; 68 y[tail]:=y[head]+fy[j]; 69 vis[x[tail],y[tail]]:=false; 70 f[x[tail],y[tail],i]:=f[x[head],y[head],i]+1; 71 flag[x[tail],y[tail]]:=false; 72 end; 73 inc(head); 74 end; 75 end; 76 for i:=1 to n do 77 for j:=1 to m do 78 if (map[i,j]='.')and(vis[i,j]) then 79 begin 80 write('impossible'); 81 halt; 82 end; 83 end; 84 85 var 86 a:array[0..410,0..410]of longint; 87 dis,vh,pre,his:array[0..410]of longint; 88 flow,time,aug,num,min,hui:longint; 89 find:boolean; 90 91 procedure sap; 92 var 93 i,j,k:longint; 94 begin 95 aug:=maxlongint; 96 fillchar(vh,sizeof(vh),0); 97 vh[0]:=num+1; 98 fillchar(dis,sizeof(dis),0); 99 i:=0; 100 while dis[0]<=num do 101 begin 102 his[i]:=aug; 103 find:=false; 104 for j:=0 to num+1 do 105 if (a[i,j]>0)and(dis[i]=dis[j]+1) then 106 begin 107 find:=true; 108 if aug>a[i,j] then aug:=a[i,j]; 109 pre[j]:=i; 110 i:=j; 111 if i=hui then 112 begin 113 inc(flow,aug); 114 while i<>0 do 115 begin 116 k:=pre[i]; 117 inc(a[i,k]); 118 dec(a[k,i]); 119 i:=k; 120 end; 121 aug:=maxlongint; 122 end; 123 break; 124 end; 125 if find then continue; 126 min:=num; 127 for j:=0 to num+1 do 128 if (a[i,j]>0)and(min>dis[j]) then min:=dis[j]; 129 dec(vh[dis[i]]); 130 inc(vh[min+1]); 131 if vh[dis[i]]=0 then break; 132 dis[i]:=min+1; 133 if i<>0 then 134 begin 135 i:=pre[i]; 136 aug:=his[i]; 137 end; 138 end; 139 end; 140 141 procedure work; 142 var 143 i,j,k:longint; 144 begin 145 num:=menn+doorn+1; 146 hui:=num+1; 147 for i:=1 to n do 148 for j:=1 to m do 149 if map[i,j]='.' then inc(a[0,node[i,j]]); 150 while flow<menn do 151 begin 152 inc(time); 153 for i:=1 to n do 154 for j:=1 to m do 155 if map[i,j]='.' then 156 for k:=1 to doorn do 157 if f[i,j,k]=time then inc(a[node[i,j],node[door[k,0],door[k,1]]]); 158 for i:=1 to doorn do 159 inc(a[node[door[i,0],door[i,1]],hui]); 160 sap; 161 end; 162 write(time); 163 end; 164 165 begin 166 init; 167 bfs; 168 work; 169 end.