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
XXXXX
X...D
XX.XX
X..XX
XXDXX
Sample Output
3
题解
话说搜索可以骗70分,考虑一群人可以从几个门出去,去个平均数,不能整除则加1,取每一块的最大值。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<algorithm> using namespace std; int n,m,tot,peop,usd,mark[22][22],bs[22][22],ans=-1; char map[22][22]; struct message{int x,y;} d[105],q[405]; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; void init() { scanf("%d%d",&n,&m); int i,j; for(i=0;i<n;i++) {scanf("%s",map[i]); for(j=0;j<m;j++) {if(map[i][j]=='D') {tot++; d[tot].x=i; d[tot].y=j;} else if(map[i][j]=='.') peop++; } } } bool check(int x,int y) { if(x<0||y<0||x>=n||y>=m) return true; if(map[x][y]=='X') return true; return false; } void bfs(int sx,int sy) { int i,t=0,w=1,tx,ty,nx,ny; int sum=0,div=1; memset(bs,-1,sizeof(bs)); q[t].x=sx; q[t].y=sy; bs[sx][sy]=0; while(t!=w) {nx=q[t].x; ny=q[t].y; t=(t+1)%(n*m); for(i=0;i<4;i++) {tx=nx+xx[i]; ty=ny+yy[i]; if(bs[tx][ty]!=-1) continue; if(check(tx,ty)) continue; if(map[tx][ty]=='.') {sum++; q[w].x=tx; q[w].y=ty; w=(w+1)%(n*m); bs[tx][ty]=bs[nx][ny]+1; } else if(map[tx][ty]=='D') {div++; mark[tx][ty]=1;} } } usd+=sum; if(sum%div==0) ans=max(ans,sum/div); else ans=max(ans,(sum/div)+1); } void work() { int i; for(i=1;i<=tot;i++) {if(mark[d[i].x][d[i].y]==1) continue; mark[d[i].x][d[i].y]=1; bfs(d[i].x,d[i].y); } if(usd>=peop) printf("%d\n",ans); else puts("impossible"); } int main() { //freopen("data.in","r",stdin); //freopen("data.out","w",stdout); init(); work(); return 0; }
正解二分+网络流,二分最大值,每次暴力建图即可。
#include<cstdio> #include<cstring> #include<cstdlib> #include<iostream> #include<cmath> #include<algorithm> #define S 401 #define T 402 #define inf 1<<30 using namespace std; int n,m,tot,peop,bs[25][25],dis[25][25][100]; char map[25][25]; struct wu{int x,y;} d[100],q[405]; int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0}; int h[405],zz,head[405],ans,dui[405]; struct bian{int to,nx,v;} e[800000]; //------------------------------------------------------------------------------ void init() { scanf("%d%d",&n,&m); int i,j; for(i=0;i<n;i++) {scanf("%s",map[i]); for(j=0;j<m;j++) {if(map[i][j]=='D') {tot++; d[tot].x=i; d[tot].y=j;} else if(map[i][j]=='.') peop++; } } } bool check(int x,int y) { if(x<0||y<0||x>=n||y>=m) return true; if(bs[x][y]!=-1||map[x][y]=='X'||map[x][y]=='D') return true; return false; } void prebfs(int sx,int sy) { int i,t=0,w=1,nx,ny,tx,ty; memset(bs,-1,sizeof(bs)); q[0].x=sx; q[0].y=sy; bs[sx][sy]=0; while(t!=w) {nx=q[t].x; ny=q[t].y; t=(t+1)%(n*m); for(i=0;i<4;i++) {tx=nx+xx[i]; ty=ny+yy[i]; if(check(tx,ty)) continue; q[w].x=tx, q[w].y=ty; w=(w+1)%(n*m); bs[tx][ty]=bs[nx][ny]+1; } } } void pre() { int i,j,k; memset(dis,127,sizeof(dis)); for(i=1;i<=tot;i++) {prebfs(d[i].x,d[i].y); for(j=0;j<n;j++) for(k=0;k<m;k++) {if(bs[j][k]!=-1) dis[j][k][i]=bs[j][k]; } } } //------------------------------------------------------------------------------ void insert(int x,int y,int z) { zz++; e[zz].to=y; e[zz].v=z; e[zz].nx=head[x]; head[x]=zz; zz++; e[zz].to=x; e[zz].v=0; e[zz].nx=head[y]; head[y]=zz; } void rebuild(int f) { int i,j,k,x,y; memset(head,0,sizeof(head)); zz=1; for(i=0;i<n;i++) for(j=0;j<m;j++) {if(map[i][j]!='.') continue; x=i*m+j; insert(S,x,1); for(k=1;k<=tot;k++) {if(dis[i][j][k]<=f) {y=d[k].x*m+d[k].y; insert(x,y,1); } } } for(i=1;i<=tot;i++) {x=d[i].x*m+d[i].y; insert(x,T,f);} } bool bfs() { memset(h,-1,sizeof(h)); int i,t=0,w=1,x,p; h[S]=0; dui[0]=S; while(t<w) {x=dui[t]; t++; for(i=head[x];i;i=e[i].nx) {p=e[i].to; if(h[p]<0&&e[i].v) {h[p]=h[x]+1; dui[w]=p; w++; } } } if(h[T]==-1) return false; return true; } int dfs(int x,int f) { if(x==T) return f; int usd=0,rest,p,i; for(i=head[x];i;i=e[i].nx) {p=e[i].to; if(h[p]==h[x]+1&&e[i].v) {rest=f-usd; rest=dfs(p,min(rest,e[i].v)); e[i].v-=rest; e[i^1].v+=rest; usd+=rest; if(usd==f) return f; } } if(!usd) h[x]=-1; return usd; } bool judge(int x) { rebuild(x); int sum=0; while(bfs()) sum+=dfs(S,inf); if(sum==peop) return true; else return false; } void work() { int l=1,r=peop,mid; ans=-1; while(l<=r) {mid=(l+r)>>1; if(judge(mid)) {ans=mid; r=mid-1;} else l=mid+1; } if(ans==-1) puts("impossible"); else printf("%d\n",ans); } //------------------------------------------------------------------------------ int main() { freopen("data.in","r",stdin); freopen("data.out","w",stdout); init(); pre(); work(); return 0; }