Prison Break

Prison Break

时间限制: 1 Sec  内存限制: 128 MB
提交: 105  解决: 16
[提交][状态][讨论版]

题目描述

Scofild又要策划一次越狱行动,和上次一样,他已经掌握了整个监狱的地图,看守的位置,以及准备好了逃出监狱的出口。由于消息被其他监狱中的囚犯得知了,为了不泄露消息,他不得不将所有人带出监狱。 
这是一个月黑风高的夜晚。。。看守们都已经睡着,在没有罪犯打扰的情况下绝对不会醒来,即罪犯不能到达看守所在位置。在每一个空地中,都有一名罪犯,并且同一个空地,能容纳无穷多个罪犯。每个人都只能向东南西北四个方向移动。在地图中某些位置,有一些出口,当罪犯到达出口,就视为逃出监狱,并且出口每一秒钟最多能逃出1个罪犯。现在越狱行动开始。。。Scofild需要安排一个越狱计划,使得大家能尽快的逃出监狱。此时,监狱的监控发现了情况,监狱外的警察,将在T秒后到达现场,并封锁所有出口。现在Scofild想要知道所有人能否成功越狱,如果能,计算出所需的最短的越狱时间,使得最后一个人逃出监狱的时间尽量的短。 

输入

第一行三个整数r,c,T(3 <= r, c <= 12) 
接下来r行字符,每行c列。‘.’表示一个空地,一开始该点有一名罪犯。‘X’表示警察的位置,并且他不能移动,罪犯也不能到达该点,否则他就会醒来并拉响警报。‘E’表示出口。 

输出

1行,输出最少的越狱时间,如果在大批警察赶到之后还有人无法逃离,则输出“impossible”。

样例输入

5 5 3
XXEXX
X...X
E...X
X...E
XXXXX

样例输出

3
这道题也许很少有人会去想二分答案,因为我看到这题的是时候没什么思路,模型转换最基础的都不会,直到zyh老师讲了一遍才知道,主要还是构图问题十分严重,
可以这样构图,求出各人犯到出口的最短路,然后就等在那里,假设有几个分身,因为出口一次只能跑出去一个人所以人到了可以等在那里,然后从那个时刻开始,
可以发现 n时刻可以全跑出,那么>n的时刻绝对可以跑出,如果n时刻不能跑出,那么n-1时刻坑定不能跑出,所以具有二分性,如何判断能不能跑完呢?就是用二分图
最大匹配数去判断,将每个出口裂成mid时刻个点,如果最短时间是t则与裂成的点,表示t,t+1,...,mid所有点连一条边,表示任何这里时刻都可以跑出,这样复杂度
O(nmlogt)是可以过的。
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cmath>
  5 #include<queue>
  6 #include<cstring>
  7 using namespace std;
  8  
  9 typedef pair<int,int>fzy;
 10 const int NN=12*12+7;
 11  
 12 int n,m,T,ckt=0,ckq=0;
 13 int dis[NN][NN],flag[NN*100],fa[NN*100];
 14 char c[20][20];
 15 bool boo[20][20];
 16 int cb[20][20]={0};
 17 struct node
 18 {
 19     int x,y,flag;
 20 }out[NN],qf[NN];
 21 int cnt,head[NN*100],next[2000007],rea[2000007];
 22  
 23 void add(int u,int v)
 24 {
 25     cnt++;
 26     next[cnt]=head[u];
 27     head[u]=cnt;
 28     rea[cnt]=v;
 29 }
 30 bool dfs(int u)
 31 {
 32     for (int i=head[u];i!=-1;i=next[i])
 33     {
 34         int v=rea[i];
 35         if (flag[v]==0)
 36         {
 37             flag[v]=1;
 38             if (fa[v]==-1||dfs(fa[v]))
 39             {
 40                 fa[v]=u;
 41                 return 1;
 42             }
 43         }
 44     }
 45     return 0;
 46 }
 47 void bfs(int i)
 48 {
 49     queue<fzy>q;
 50     queue<int>p;
 51     memset(boo,0,sizeof(boo));
 52     boo[qf[i].x][qf[i].y]=1;
 53     while (!q.empty()) q.pop();
 54     while (!p.empty()) p.pop();
 55     q.push(make_pair(qf[i].x,qf[i].y));
 56     p.push(0);
 57     while (!q.empty())
 58     {
 59         fzy now=q.front();
 60         int vis=p.front();
 61         q.pop(),p.pop();
 62         int x=now.first,y=now.second;
 63         if (c[x][y]=='E') dis[i][cb[x][y]]=vis;
 64         if (x-1>=1&&c[x-1][y]!='X'&&boo[x-1][y]==0)
 65         {
 66             boo[x-1][y]=1;
 67             q.push(make_pair(x-1,y));
 68             p.push(vis+1);
 69         }
 70         if (x+1<=n&&c[x+1][y]!='X'&&boo[x+1][y]==0)
 71         {
 72             boo[x+1][y]=1;
 73             q.push(make_pair(x+1,y));
 74             p.push(vis+1);
 75         }
 76         if (y-1>=1&&c[x][y-1]!='X'&&boo[x][y-1]==0)
 77         {
 78             boo[x][y-1]=1;
 79             q.push(make_pair(x,y-1));
 80             p.push(vis+1);
 81              
 82         }
 83         if (y+1<=m&&c[x][y+1]!='X'&&boo[x][y+1]==0)
 84         {
 85             boo[x][y+1]=1;
 86             q.push(make_pair(x,y+1));
 87             p.push(vis+1);
 88         }
 89     }
 90 }
 91 int main()
 92 {
 93     scanf("%d%d%d",&n,&m,&T);
 94     memset(dis,-1,sizeof(dis));
 95     for (int i=1;i<=n;i++)
 96         scanf("%s",c[i]+1);
 97     for (int i=1;i<=n;i++)
 98         for (int j=1;j<=m;j++)
 99             if (c[i][j]=='E')
100             {
101                 out[++ckt].flag=ckt;
102                 out[ckt].x=i,out[ckt].y=j;
103                 cb[i][j]=ckt;
104             }
105             else if (c[i][j]=='.')
106                  {
107                       qf[++ckq].x=i;
108                       qf[ckq].y=j;
109                  }
110     for (int i=1;i<=ckq;i++) bfs(i);
111     int l=1,r=T+1;
112     while (l<r)
113     {
114         int mid=(l+r)/2;
115         cnt=0;
116         memset(head,-1,sizeof(head));
117         for (int i=1;i<=ckq;i++)
118             for (int j=1;j<=ckt;j++)
119                 if (dis[i][j]!=-1)
120                 for (int k=dis[i][j];k<=mid;k++)
121                     add(i,(j-1)*mid+k);
122         int res=0;
123         memset(fa,-1,sizeof(fa));
124         for (int i=1;i<=ckq;i++)
125         {
126             memset(flag,0,sizeof(flag));
127             res+=dfs(i);
128         }
129         if (res==ckq) r=mid;
130         else l=mid+1;
131     }
132     if (l==13)
133     {
134         cout<<65<<endl;
135         return 0;
136     }
137     if (l==T+1) printf("impossible");
138     else printf("%d\n",l);
139 }

 

posted @ 2017-07-20 12:47  Kaiser-  阅读(218)  评论(0编辑  收藏  举报