码迷,mamicode.com
首页 > 其他好文 > 详细

[HNOI2007]紧急疏散evacuate

时间:2017-07-30 23:49:03      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:stream   inline   check   double   字符   code   out   ret   他也   

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
 
solution:
(ps:这题有两个SB的错误,结果调了一个晚上......)
首先要bfs求出每个人到  各个门的  距离,如果有一个人一个门都到不了,  impossible
由于用的时间有单调性,所以二分时间
建模:
将门按时间分成 各个时间段的点
S向各个人连 1 的边
每个人向他能到的各个门 最短时间之后的门连一条 1 的边
每个门 每个时间段的点 向T连边
(但是我觉得popoqqq担心的,我没有这个问题,我的程序能过)
卡了一个晚上
1.这个点向每一个能到的门 都得连边!!!!!
2.存边数组又开小了
技术分享
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<iostream>
  5 #define mem(a,b) memset(a,b,sizeof(a))
  6 #define ll long long
  7 #define dd double
  8 using namespace std;
  9 const int INF=(1<<31)-1;
 10 inline int maxn(int a,int b){return a>b?a:b;}
 11 inline int minn(int a,int b){return a<b?a:b;}
 12 char readchar()
 13 {
 14     char q=getchar();
 15     while(q!=.&&q!=X&&q!=D)q=getchar();
 16     return q;
 17 }
 18 struct son
 19 {
 20     int u,v,next,w;
 21 };
 22 son a1[1000001];
 23 int first[1000001],e;
 24 
 25 void addbian(int u,int v,int w)
 26 {
 27     a1[e].v=v;
 28     a1[e].w=w;
 29     a1[e].u=u;
 30     a1[e].next=first[u];
 31     first[u]=e++;
 32 }
 33 void Link(int u,int v,int w){addbian(u,v,w);addbian(v,u,0);}
 34 int dui[10000001];
 35 int he,en;
 36 inline void clear(){he=1;en=0;}
 37 inline void pop(){++he;}
 38 inline bool empty(){return en>=he?0:1;}
 39 inline int top(){return dui[he];}
 40 inline void push(int x){dui[++en]=x;}
 41 
 42 int n,m,S,T,dmax,sumdoor;
 43 int ha[56][56][506];
 44 int panduan;
 45 char a[56][56];
 46 
 47 struct son1
 48 {
 49     int x,y,val;
 50 };
 51 son1 ji[56][56][506];
 52 int num[56][56];
 53 
 54 queue<son1> q;
 55 
 56 bool flag[56][56];
 57 void Bfs(int x,int y)
 58 {
 59     while(!q.empty())q.pop();
 60     mem(flag,0);
 61     son1 now=(son1){x,y,0};
 62     q.push(now);flag[x][y]=1;
 63     while(!q.empty())
 64     {
 65         now=q.front();q.pop();
 66         //printf("%d %d %d\n",now.x,now.y,now.val);
 67         if(a[now.x][now.y]==D){ji[x][y][++num[x][y]]=now;continue;}
 68         //flag在push进来之后就要标记,不然你懂得 
 69         if(now.x>1&&!flag[now.x-1][now.y]&&a[now.x-1][now.y]!=X){q.push((son1){now.x-1,now.y,now.val+1});flag[now.x-1][now.y]=1;}
 70         if(now.x<n&&!flag[now.x+1][now.y]&&a[now.x+1][now.y]!=X){q.push((son1){now.x+1,now.y,now.val+1});flag[now.x+1][now.y]=1;}
 71         if(now.y>1&&!flag[now.x][now.y-1]&&a[now.x][now.y-1]!=X){q.push((son1){now.x,now.y-1,now.val+1});flag[now.x][now.y-1]=1;}
 72         if(now.y<m&&!flag[now.x][now.y+1]&&a[now.x][now.y+1]!=X){q.push((son1){now.x,now.y+1,now.val+1});flag[now.x][now.y+1]=1;}
 73     }
 74     if(!num[x][y])
 75       panduan=1;
 76 }
 77 
 78 int dep[200006];
 79 int bfs()
 80 {
 81     mem(dep,0);clear();
 82     dep[S]=1;push(S);
 83     while(!empty())
 84     {
 85         int now=top();pop();
 86         //printf("now=%d\n",now);
 87         for(int i=first[now];i!=-1;i=a1[i].next)
 88         {
 89             int temp=a1[i].v;
 90             if(dep[temp]||!a1[i].w)continue;
 91             dep[temp]=dep[now]+1;
 92             push(temp);
 93             if(temp==T)return 1;
 94         }
 95     }
 96     return 0;
 97 }
 98 
 99 int dfs(int x,int val)
100 {
101     //printf("x=%d T=%d\n",x,T);
102     if(x==T)return val;
103     int val2=val,k;
104     for(int i=first[x];i!=-1;i=a1[i].next)
105     {
106         int temp=a1[i].v;
107         //printf("x=%d temp=%d\n",x,temp);
108         if(!a1[i].w||dep[temp]!=dep[x]+1||!val2)continue;
109         k=dfs(temp,minn(val2,a1[i].w));
110         if(!k){dep[temp]=0;continue;}
111         a1[i].w-=k;a1[i^1].w+=k;val2-=k;
112     }
113     return val-val2;
114 }
115 
116 int Dinic()
117 {
118     int ans=0;
119     //cout<<1;
120     while(bfs())
121     {
122         //cout<<2;
123       ans+=dfs(S,INF);
124     }
125     return ans;
126 }
127 
128 void chu()
129 {
130     mem(ha,0);
131     mem(a1,0);
132     mem(first,-1);
133     e=0;
134 }
135 
136 int check(int time)
137 {
138     chu();
139     
140     int now=0,ren;
141     for(int i=1;i<=n;++i)
142       for(int j=1;j<=m;++j)
143         if(a[i][j]==.)
144             ha[i][j][0]=++now;
145     ren=now;
146     for(int i=1;i<=n;++i)
147       for(int j=1;j<=m;++j)
148         if(a[i][j]==D)
149           for(int k=1;k<=time;++k)
150             ha[i][j][k]=++now;
151     S=0;T=now+1;
152     //printf("ren=%d\n",ren);
153     for(int i=1;i<=ren;++i)Link(S,i,1);
154     for(int i=1;i<=n;++i)
155       for(int j=1;j<=m;++j)
156         if(a[i][j]==.)
157           for(int l=1;l<=num[i][j];++l)
158               for(int k=ji[i][j][l].val;k<=time;++k)
159                         Link(ha[i][j][0],ha[ji[i][j][l].x][ji[i][j][l].y][k],1);
160     
161     for(int i=1;i<=n;++i)
162       for(int j=1;j<=m;++j)
163         if(a[i][j]==D)
164           for(int k=1;k<=time;++k)
165                     Link(ha[i][j][k],T,1);
166     //printf("now=%d\n",now);
167     //printf("e=%d\n",e);
168     return Dinic()==ren;
169 }
170 
171 int er(int l,int r)
172 {
173     //printf("l=%d r=%d\n",l,r);
174     if(l==r)
175       return l;
176     int mid=(l+r)>>1;
177     if(check(mid))
178       return er(l,mid);
179     else
180       return er(mid+1,r);
181 }
182 
183 int main(){
184     //freopen("1.txt","r",stdin);
185     //freopen("data6.in","r",stdin);
186     scanf("%d%d",&n,&m);
187     for(int i=1;i<=n;++i)
188       for(int j=1;j<=m;++j)
189       {a[i][j]=readchar();if(a[i][j]==D)++sumdoor;}
190     //cout<<0;
191     for(int i=1;i<=n;++i)
192       for(int j=1;j<=m;++j)
193             if(a[i][j]==.)
194                 Bfs(i,j);
195     //printf("%d\n",ji[11][4].val);
196     //cout<<0;
197     //printf("dmax=%d\n",dmax);
198     //printf("ssss=%d %d\n",dmax,n*m+1);
199     if(panduan)puts("impossible");
200     else
201         printf("%d",er(1,n*m+1));
202     //while(1);
203     return 0;
204 }
code

 

[HNOI2007]紧急疏散evacuate

标签:stream   inline   check   double   字符   code   out   ret   他也   

原文地址:http://www.cnblogs.com/A-LEAF/p/7260612.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!