zoukankan      html  css  js  c++  java
  • 【BZOJ1189】[HNOI2007]紧急疏散evacuate 动态加边网络流

    【BZOJ1189】[HNOI2007]紧急疏散evacuate

    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

    题解:这题网上好多题解都过不了,自己也狂WA不止,还好有小号交题大法~

    先以每个门为起点进行BFS,将每个门按照时间拆点,设i号位置到j号门的距离为dis,则

    i -> (j,dis) 容量1
    S -> i 容量1

    然后枚举时间,动态加边,设当前时间为tim,则

    (j,tim-1) -> (j,tim) 容量∞
    (j,tim) -> T 容量1

    然后注意BFS的时候只能访问'.'的点,不能访问其他的门

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #define tx (i+dx[k])
    #define ty (j+dy[k])
    #define P(A,B) ((A-1)*m+B)
    using namespace std;
    int to[4000010],next[4000010],val[4000010],head[200000],d[200000],dis[30][30];
    int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
    int n,m,cnt,S,T,ans,tim,tot,dor;
    char str[30][30];
    queue<int> q,qx,qy;
    int dfs(int x,int mf)
    {
    	if(x==T)	return mf;
    	int i,temp=mf,k;
    	for(int i=head[x];i!=-1;i=next[i])
    	{
    		if(d[to[i]]==d[x]+1&&val[i])
    		{
    			k=dfs(to[i],min(temp,val[i]));
    			if(!k)	d[to[i]]=0;
    			val[i]-=k,val[i^1]+=k,temp-=k;
    			if(!temp)	break;
    		}
    	}
    	return mf-temp;
    }
    int bfs()
    {
    	memset(d,0,sizeof(d));
    	while(!q.empty())	q.pop();
    	int i,u;
    	q.push(S),d[S]=1;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop();
    		for(i=head[u];i!=-1;i=next[i])
    		{
    			if(!d[to[i]]&&val[i])
    			{
    				d[to[i]]=d[u]+1;
    				if(to[i]==T)	return 1;
    				q.push(to[i]);
    			}
    		}
    	}
    	return 0;
    }
    void add(int a,int b,int c)
    {
    	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
    }
    void getdis(int x,int y)
    {
    	memset(dis,0,sizeof(dis));
    	qx.push(x),qy.push(y);
    	int i,j,k;
    	while(!qx.empty())
    	{
    		i=qx.front(),j=qy.front(),qx.pop(),qy.pop();
    		for(k=0;k<4;k++)	if(!dis[tx][ty]&&tx&&tx<=n&&ty&&ty<=m&&str[tx][ty-1]=='.')
    		{
    			dis[tx][ty]=dis[i][j]+1;
    			add(P(tx,ty),P(x,y)+(dis[tx][ty]-1)*n*m,1);
    			qx.push(tx),qy.push(ty);
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int i,j,k;
    	S=0,T=n*m*n*m+1;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	scanf("%s",str[i]);
    	for(i=1;i<=n;i++)	for(j=1;j<=m;j++)
    	{
    		if(str[i][j-1]=='.')	tot++,add(S,P(i,j),1);
    		if(str[i][j-1]=='D')	getdis(i,j);
    	}
    	while(ans<tot)
    	{
    		if(tim>=n*m)
    		{
    			printf("impossible");
    			return 0;
    		}
    		for(i=1;i<=n;i++)	for(j=1;j<=m;j++)
    		{
    			if(str[i][j-1]=='D')
    			{
    				add(P(i,j)+tim*n*m,T,1);
    				if(tim)		add(P(i,j)+(tim-1)*n*m,P(i,j)+tim*n*m,1<<30);
    			}
    		}
    		tim++;
    		while(bfs())	ans+=dfs(S,1<<30);
    	}
    	printf("%d",tim);
    	return 0;
    }
  • 相关阅读:
    201871010132-张潇潇-作业四 软件研发团队组建
    201871010132-张潇潇 实验三 结对项目—《D{0-1}KP 实例数据集算法实验平台》项目报告
    201871010132-张潇潇 实验二 个人项目—《西北师范大学学生疫情上报系统》项目报告
    201871010132-张潇潇 实验一软件工程准备-软件工程初识
    张潇潇--学期获奖总结
    201871010132--张潇潇--《面向对象程序设计(java)》课程总结
    201871010132--张潇潇--《面向对象程序设计(java)》第十七周学习总结
    201871010132--张潇潇--《面向对象程序设计(java)》第十六周学习总结
    201871010132--张潇潇--《面向对象程序设计(java)》第十五周学习总结
    201871010132--张潇潇--《面向对象程序设计(java)》第十四周学习总结
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6882023.html
Copyright © 2011-2022 走看看