zoukankan      html  css  js  c++  java
  • [洛谷P3851] TJOI2007 脱险

    问题背景

    一批探险队员正在一个迷宫一样的山洞里摸索,突然他们得到了一个糟糕的消息,由于附近发生地震,这个山洞将有可能在T个单位时间后坍塌。现在他们要用最快的速度找出一个方案,使得在T个单位时间内逃出的队员最多。已知探险队员在一个单位时间内可以向前后左右任一方向移动一格,也可以停留在原地不动。有一个糟糕的情况是,虽然山洞的内部比较宽敞,但山洞的出口都非常狭窄,一个单位时间只能允许一名队员通过。

    问题描述

    山洞的地图用一个R * C的字符矩阵表示,其中'.'表示在开始的时候没有探险队员的空地,空地可以容纳任意多的探险队员;'P'表示在开始的时候有探险队员的空地,我们假设在开始的时候所有的队员都在不同的位置上,且没有队员恰好位于出口所在的方格;' * '表示障碍物,探险队员不能经过被障碍物占据的方格;'O'(大写字母O)表示出口,输入数据保证出口一定位于地图的边界上,即只有第1行,第R行,第1列,第C列有可能出现'O'。另外,输入数据保证整个地图被边界和出口围住,即第1行,第R行,第1列,第C列只能是'*'或'O'.

    输入格式

    输入文件的第一行是用空格隔开的两个整数R和C,表示地图的大小。第二行是整数T,即山洞将要坍塌的时间。接下来R行,每行包含C个字符,表示一幅山洞地图。

    输出格式

    输出一行,包含一个整数,即T个单位时间内最多能逃出的人数。

    样例输入

    5 5
    4
    *****
    *P..*
    O**.O
    *P..*
    *****
    

    样例输出

    1
    

    说明

    山洞有两个出口,但只有右边的出口是可以到达的。虽然在3个单位时间内两人都可以到达出口左侧的方格处,但由于在出口处一个单位时间只能允许一人通过,故4个单位时间内只能逃出一人。两人都逃出需要5个单位时间。

    对于30%的数据,队员数和出口数均不超过10

    对于100%的数据,3 ≤ R, C ≤ 12,0 < T ≤ 50

    解析

    首先BFS出每个人到每一个出口的距离,然后网络流建图,对每一个出口都建T个点,向汇点连容量为1的边,表示在这个时刻只能通过1人。对于每个人,向每一个时间不小于自己到那个出口的距离的点连边,容量为1。Dinic即可。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define N 1000002
    #define M N
    using namespace std;
    const int inf=1<<30;
    int head[N],ver[M*2],nxt[M*2],cap[M*2],l;
    struct node{
    	int x,y,d;
    	node(int _x,int _y,int _d){
    		x=_x,y=_y,d=_d;
    	}
    };
    int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
    int r,c,t,i,j,k,n,m,n1,n2,S,T,dis[N],flow[N],pre[N],cnt[N],id[102][102],dist[102][102],ans;
    char a[50][50];
    bool vis[50][50],in[N];
    void bfs(int sx,int sy,int p)
    {
    	queue<node> q;
    	memset(vis,0,sizeof(vis));
    	q.push(node(sx,sy,0));
    	vis[sx][sy]=1;
    	while(!q.empty()){
    		int x=q.front().x,y=q.front().y,d=q.front().d;
    		q.pop();
    		for(int i=0;i<4;i++){
    			int tx=x+dx[i],ty=y+dy[i];
    			if(tx>=1&&tx<=r&&ty>=1&&ty<=c&&a[tx][ty]!='*'&&!vis[tx][ty]){
    				vis[tx][ty]=1;
    				if(a[tx][ty]=='O') dist[p][id[tx][ty]]=d+1;
    				q.push(node(tx,ty,d+1));
    			}
    		}
    	}
    }
    void insert(int x,int y,int z)
    {
    	ver[l]=y;
    	cap[l]=z;
    	nxt[l]=head[x];
    	head[x]=l;
    	l++;
    	ver[l]=x;
    	cap[l]=0;
    	nxt[l]=head[y];
    	head[y]=l;
    	l++;
    }
    bool bfs()
    {
    	queue<int> q;
    	memset(dis,-1,sizeof(dis));
    	q.push(S);
    	dis[S]=0;
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		for(int i=head[x];i!=-1;i=nxt[i]){
    			int y=ver[i];
    			if(dis[y]==-1&&cap[i]>0){
    				dis[y]=dis[x]+1;
    				q.push(y);
    			}
    		}
    	}
    	return (dis[T]!=-1);
    }
    int dfs(int x,int flow)
    {
    	if(x==T||flow==0) return flow;
    	int ans=0;
    	for(int i=head[x];i!=-1;i=nxt[i]){
    		int y=ver[i];
    		if(dis[y]==dis[x]+1&&cap[i]>0){
    			int a=dfs(y,min(flow,cap[i]));
    			flow-=a;ans+=a;
    			cap[i]-=a;cap[i^1]+=a;
    		}
    		if(flow==0) break;
    	}
    	if(flow) dis[x]=-1;
    	return ans;
    }
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d%d",&r,&c,&t);
    	for(i=1;i<=r;i++) scanf("%s",a[i]+1);
    	for(i=1;i<=r;i++){
    		for(j=1;j<=c;j++){
    			if(a[i][j]=='P') id[i][j]=++n1;
    		}
    	}
    	for(i=1;i<=r;i++){
    		for(j=1;j<=c;j++){
    			if(a[i][j]=='O') id[i][j]=(++n2)+n1;
    		}
    	}
    	for(i=1;i<=r;i++){
    		for(j=1;j<=c;j++){
    			if(a[i][j]=='P') bfs(i,j,id[i][j]);
    		}
    	}
    	n=n1+n2*t+1,T=n;
    	for(i=1;i<=n1;i++) insert(S,i,1);
    	for(i=n1+1;i<=n1+n2*t;i++) insert(i,T,1);
    	for(i=1;i<=t;i++){
    		for(j=1;j<=n1;j++){
    			for(k=n1+1;k<=n1+n2;k++){
    				if(dist[j][k]<=i&&dist[j][k]!=0){
    					insert(j,n1+(k-n1-1)*t+i,1);
    				}
    			}
    		}
    	}
    	while(bfs()) ans+=dfs(S,inf);
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Storm分布式实时流计算框架相关技术总结
    上手开源项目的几点建议【转】
    笔试面试的路上——努力ing
    Storm配置项详解【转】
    storm UI
    leetcode-单词探索
    leetcode-全排列详解(回溯算法)
    leetcode-生成括号(回溯算法)
    leetcode-递增的三元子序列
    leetcode-最长无重复字符的子串
  • 原文地址:https://www.cnblogs.com/LSlzf/p/13291385.html
Copyright © 2011-2022 走看看