zoukankan      html  css  js  c++  java
  • C++之路进阶——codevs3566(紧急疏散)

    3566 紧急疏散

     

     时间限制: 1 s
     空间限制: 128000 KB
     题目等级 : 黄金 Gold
     
     
    题目描述 Description

    发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域。每个格子如果是'.',那么表示这是一块空地;如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间。已知门一定在房间的边界上,并且边界上不会有空地。最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都可以向上下左右四个方向移动一格,当然他也可以站着不动。疏散开始后,每块空地上就没有人数限制了(也就是说每块空地可以同时站无数个人)。但是,由于门很窄,每一秒钟只能有一个人移动到门的位置,一旦移动到门的位置,就表示他已经安全撤离了。现在的问题是:如果希望所有的人安全撤离,最短需要多少时间?或者告知根本不可能。

    输入描述 Input Description

    输入文件第一行是由空格隔开的一对正整数N与M,3<=N <=20,3<=M<=20,以下N行M列描述一个N M的矩阵。其中的元素可为字符'.'、'X'和'D',且字符间无空格。

    输出描述 Output Description

    只有一个整数K,表示让所有人安全撤离的最短时间,如果不可能撤离,那么输出'impossible'(不包括引号).

    样例输入 Sample Input

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

    样例输出 Sample Output

    3

    数据范围及提示 Data Size & Hint

    3<=N <=20,3<=M<=20

    题解: 

      对于每个门进行一次bfs,得出每个点到每个门的时间
     然后二分时间,每次建图dinic
     S到空地连一条容量1的边,
     每个空地到可到达的门连一条容量1的边,
     每个门到T连一条容量为时间的边

    代码:

    (对于codevs来说):

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define INF 0x7fffffff 
      7 #define maxn 1001
      8 #define S 0
      9 #define T 1000
     10 
     11 using namespace std;
     12 
     13 int n,m,head[maxn],dis[401][21][21],ans,tot,cnt=1,door=1,layered[maxn],map[21][21],finallyans=-1;
     14 int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
     15 
     16 struct ss
     17    {
     18         int x;
     19         int y;
     20         int s;
     21         ss() {};
     22         ss(int a,int b,int c)
     23           {
     24                 x=a;
     25                 y=b;
     26                 s=c;
     27           };
     28    };
     29    
     30 struct node
     31    {
     32         int to;
     33      int next;
     34      int edge;      
     35    }e[1000001];
     36 
     37 void add(int u,int v,int c)
     38   {
     39       e[++cnt].to=v;
     40       e[cnt].next=head[u];
     41       e[cnt].edge=c;
     42       head[u]=cnt;
     43   }
     44 
     45 void insert(int u,int v,int c)
     46    {
     47      add(u,v,c);
     48      add(v,u,0);     
     49    }
     50    
     51 bool bfs()
     52    {
     53         for (int i=1;i<=T;i++) layered[i]=INF;
     54         queue<int>que;
     55         que.push(S);
     56         while (!que.empty())
     57            {
     58               int now=que.front();
     59            que.pop();
     60            for (int i=head[now];i;i=e[i].next)
     61              if (e[i].edge&&layered[e[i].to]>layered[now]+1)
     62                {
     63                    layered[e[i].to]=layered[now]+1;
     64                    que.push(e[i].to);
     65                    if (e[i].to==T) return 1;
     66                        }          
     67            }
     68     return 0;       
     69    } 
     70 
     71 int dfs(int x,int inf)
     72    {
     73         if (x==T) return inf;
     74         int rest=inf; 
     75         for (int i=head[x];i&&rest;i=e[i].next)
     76            if (e[i].edge&&layered[e[i].to]==layered[x]+1)
     77              {
     78                 int now=dfs(e[i].to,min(rest,e[i].edge));
     79                 if (!layered[now]) layered[now]=0;
     80                 e[i].edge-=now;
     81                 e[i^1].edge+=now;
     82                 rest-=now;
     83             }
     84      return inf-rest;        
     85     }
     86     
     87 int dinic()
     88     {
     89         int ansn=0;
     90         while (bfs()) ansn+=dfs(S,INF);
     91         return ansn;
     92     }
     93     
     94 void built(int x)
     95     {
     96       memset(head,0,sizeof (head));
     97       cnt=1;    
     98       for (int i=1;i<=n;i++)
     99          for (int j=1;j<=m;j++)
    100              if (map[i][j]==1)
    101                {
    102                  int v=(i-1)*m+j;
    103                  insert(S,v,1);    
    104                }
    105      for (int i=2;i<=door;i++)    insert(n*m+i,T,x);
    106      for (int i=2;i<=door;i++)
    107         for (int j=1;j<=n;j++)
    108            for (int k=1;k<=m;k++)
    109               if (dis[i][j][k]<=x) insert((j-1)*m+k,n*m+i,x);            
    110     }
    111     
    112 bool judge(int x)
    113     {
    114       built(x);
    115       int ans=dinic();
    116       if (ans==tot) return 1;
    117           else return 0;    
    118     }
    119 
    120 void search(int k,int x,int y)
    121     {
    122         queue<ss>que;
    123         que.push(ss(x,y,0));
    124         while (!que.empty())
    125            {
    126                 for (int i=0;i<4;i++)
    127                 {
    128                   int nowx=que.front().x+xx[i]; 
    129                   int nowy=que.front().y+yy[i];    
    130                   int s=que.front().s;
    131                   if(nowx<1||nowy<1||nowx>n||nowy>m||map[nowx][nowy]!=1)    continue;
    132                   if (dis[k][nowx][nowy]==INF)
    133                       {
    134                           dis[k][nowx][nowy]=s+1;
    135                           que.push(ss(nowx,nowy,s+1));
    136                       }
    137                 }       
    138                 que.pop();
    139            }    
    140     }
    141 int main()
    142     {
    143        char ch[100];
    144        scanf("%d%d",&n,&m);    
    145        for (int i=1;i<=n;i++)    
    146           {          
    147             scanf("%s",ch);
    148             for (int j=1;j<=m;j++)
    149               {
    150                  if (ch[j-1]=='.') map[i][j]=1,tot++;    
    151                  if (ch[j-1]=='D') map[i][j]=++door;         
    152                }
    153           }
    154        for (int i=2;i<=door;i++)
    155           for (int j=1;j<=n;j++)
    156              for (int k=1;k<=m;k++)
    157                  dis[i][j][k]=INF;
    158        for (int i=1;i<=n;i++)
    159           for (int j=1;j<=m;j++)
    160              if (map[i][j]>1) search(map[i][j],i,j);
    161        int l=0,r=400;
    162        while (l<=r)
    163          {
    164            int mid=(l+r)>>1;
    165            if (judge(mid)) finallyans=r=mid,r--;
    166              else l=mid+1;    
    167          }
    168        if (finallyans==-1) printf("impossible");       
    169            else printf("%d",finallyans);
    170        return 0;                                 
    171        }                                        

    对于bzoj来说:

         

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 using namespace std;
      5 #define mid (l+r)/2
      6 #define inf 0x7fffffff
      7 #define T n*n*m*m+2
      8 const int N=30;
      9 const int M=200000;
     10 char s[N];
     11 bool use[N][N],flag[N][N];
     12 struct S{int x,y,c;}l[N*N];
     13 struct Q{int st,en,va;}aa[M*2];
     14 int n,m,map[N][N],f[N][N][N][N],sum,point[M],next[M*2],cur[M],dis[M],pre[M],gap[M],tot;
     15 int xi[4]={-1,0,0,1},yi[4]={0,-1,1,0};
     16 inline void bfs(int xa,int ya){
     17     int i,h,t,k,x,y;
     18     memset(use,1,sizeof(use));
     19     h=t=1;l[h].x=xa;l[h].y=ya;l[h].c=0;
     20     while(h<=t){
     21         x=l[h].x;y=l[h].y;
     22         for(i=0;i<4;++i){
     23             int xx=x+xi[i],yy=y+yi[i];
     24             if(xx>0&&xx<=n&&yy>0&&y<=m&&map[xx][yy]==1&&use[xx][yy]){
     25                 l[++t].x=xx;l[t].y=yy;l[t].c=l[h].c+1;
     26                 use[xx][yy]=false;
     27                 f[xx][yy][xa][ya]=l[t].c;
     28                 flag[xx][yy]=true;
     29             }
     30         }
     31         h+=1;
     32     }
     33 }
     34 inline void add(int x,int y,int z){
     35     tot+=1;next[tot]=point[x];point[x]=tot;
     36     aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;
     37     tot+=1;next[tot]=point[y];point[y]=tot;
     38     aa[tot].st=y;aa[tot].en=x;aa[tot].va=0;
     39 }
     40 inline int ISAP(int ss,int tt){
     41     bool f;
     42     int minn,ans=0,i,u,y;
     43     memset(dis,0,sizeof(dis));
     44     memset(gap,0,sizeof(gap));
     45     memset(pre,0,sizeof(pre));
     46     gap[0]=tt-ss+1; u=ss;
     47     for(i=ss;i<=tt;++i) cur[i]=point[i];
     48     while(dis[ss]<tt-ss+1){
     49         f=false;
     50         for(i=cur[u];i;i=next[i])
     51           if(aa[i].va>0&&dis[u]==dis[aa[i].en]+1){
     52             cur[u]=i;f=true;break;
     53           }
     54         if(f){
     55             pre[u=aa[i].en]=i;
     56             if(u==tt){
     57                 minn=inf;
     58                 for(i=u;i!=ss;i=aa[pre[i]].st)
     59                   minn=min(minn,aa[pre[i]].va);
     60                 ans+=minn;
     61                 for(i=u;i!=ss;i=aa[pre[i]].st){
     62                     aa[pre[i]].va-=minn;
     63                     aa[pre[i]^1].va+=minn;
     64                 }
     65                 u=ss;
     66             }   
     67         }
     68         else{
     69             --gap[dis[u]];
     70             if(!gap[dis[u]]) return ans;
     71             y=2*tt; cur[u]=point[u];
     72             for(i=point[u];i;i=next[i])
     73               if(aa[i].va>0) y=min(y,dis[aa[i].st]);
     74             ++gap[dis[u]=y+1];
     75             if(u!=ss) u=aa[pre[u]].st;
     76         }
     77     }
     78     return ans;
     79 }
     80 inline bool check(int x){
     81     int i,j,p,q;
     82     tot=1;
     83     memset(point,0,sizeof(point));
     84     memset(next,0,sizeof(next));
     85     for(i=1;i<=n;++i)
     86       for(j=1;j<=m;++j){
     87         int now=((i-1)*m+j-1)*n*m;
     88         if(map[i][j]==0){
     89             for(p=1;p<x;++p)
     90               add(now+p+1,now+p+2,inf),add(now+p+1,T,1);
     91             add(now+x+1,T,1);
     92         }
     93         if(map[i][j]==1){
     94             add(1,now+1,1);
     95             for(p=1;p<=n;++p)
     96               for(q=1;q<=m;++q)
     97                 if(f[i][j][p][q])
     98                   add(now+1,((p-1)*m+q-1)*n*m+f[i][j][p][q]+1,1);
     99         }
    100       }
    101     return ISAP(1,T)==sum;
    102 }
    103 int main(){
    104     int i,j;
    105     scanf("%d%d",&n,&m);
    106     for(i=1;i<=n;++i){
    107         scanf("%s",&s);
    108         for(j=0;j<m;++j){
    109             if(s[j]=='D') map[i][j+1]=0;
    110             if(s[j]=='.') map[i][j+1]=1,sum+=1;
    111             if(s[j]=='X') map[i][j+1]=2;
    112         }
    113     }
    114     for(i=1;i<=n;++i)
    115       for(j=1;j<=m;++j)
    116         if(map[i][j]==0)
    117           bfs(i,j);
    118     for(i=1;i<=n;++i)
    119       for(j=1;j<=m;++j)
    120         if(!flag[i][j]&&map[i][j]==1){
    121             printf("impossible
    ");
    122             return 0;
    123         }
    124     int l=1,r=n*m,ans=inf;
    125     while(l<r){
    126         if(check(mid)) ans=min(ans,mid),r=mid;
    127         else l=mid+1;
    128     }
    129     printf("%d
    ",ans);
    130 }
  • 相关阅读:
    JavaScript--事件绑定及深入(26)
    JavaScript--事件对象(25)
    JavaScript--事件入门(24)
    JavaScript--动态加载脚本和样式(23)
    JavaScript--DOM元素尺寸和位置(22)
    JavaScript--DOM操作表格及样式(21)
    JavaScript--DOM进阶(20)
    jQuery-瀑布流的取巧做法分享
    Less开发指南(二)- 基本语法
    less开发指南(一)- 小牛试刀
  • 原文地址:https://www.cnblogs.com/grhyxzc/p/5211111.html
Copyright © 2011-2022 走看看