• [HNOI2007]紧急疏散evacuate


    [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 }
  • 相关阅读:
    优秀个人博客
    redis 3.0 集群__监控警报工具(sentinel)
    redis 3.0 集群__hashTag
    shell__常用命令__sed
    shell__常用命令__grep
    shell__常用命令__awk
    shell 常用命令集合
    redis 3.0 集群__配置文件详解(常用配置)
    redis 3.0 集群__故障测评
    tcp 建立连接的三次握手,以及关闭连接的4次挥手
  • 原文地址:https://www.cnblogs.com/FOXYY/p/7265883.html
Copyright © 2020-2023  润新知