zoukankan      html  css  js  c++  java
  • 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

    先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.
    View Code
  • 相关阅读:
    VBoxManage命令详解
    十条nmap常用的扫描命令
    2015-12-16 第八天笔记整理-第二部分
    2015-12-13 第八天笔记整理-第一部分
    2015-12-06 第七天课程笔记
    2015-12-04 学习笔记整理
    2015-11-22 第五天
    选择控制语句和循环结构
    数据类型和运算符
    常用DOS指令
  • 原文地址:https://www.cnblogs.com/Randolph87/p/3586799.html
Copyright © 2011-2022 走看看